24#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
25#include "mlir/IR/Location.h"
26#include "mlir/IR/Value.h"
48 bool isDivRemOp()
const {
49 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
50 opcode == BO_RemAssign;
54 bool mayHaveIntegerOverflow()
const {
56 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
57 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
69 bool isFixedPointOp()
const {
72 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
73 QualType lhstype = binOp->getLHS()->getType();
74 QualType rhstype = binOp->getRHS()->getType();
77 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
78 return unop->getSubExpr()->getType()->isFixedPointType();
83class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
85 CIRGenBuilderTy &builder;
89 bool ignoreResultAssign;
92 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
93 bool ignoreResultAssign =
false)
94 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
99 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
101 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
105 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
106 return cgf.cgm.emitNullConstant(ty, loc);
109 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
110 return builder.createFloatingCast(result, cgf.convertType(promotionType));
113 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
114 return builder.createFloatingCast(result, cgf.convertType(exprType));
117 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
119 mlir::Value maybePromoteBoolResult(mlir::Value value,
120 mlir::Type dstTy)
const {
121 if (mlir::isa<cir::IntType>(dstTy))
122 return builder.createBoolToInt(value, dstTy);
123 if (mlir::isa<cir::BoolType>(dstTy))
125 llvm_unreachable(
"Can only promote integer or boolean types");
132 mlir::Value Visit(Expr *e) {
133 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
136 mlir::Value VisitStmt(Stmt *s) {
137 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
140 mlir::Value VisitExpr(Expr *e) {
141 cgf.getCIRGenModule().errorNYI(
146 mlir::Value VisitConstantExpr(ConstantExpr *e) {
152 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
155 "ScalarExprEmitter: constant expr GL Value");
160 mlir::cast<mlir::TypedAttr>(result));
163 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
167 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
171 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
173 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
178 mlir::Value emitLoadOfLValue(
const Expr *e) {
179 LValue lv = cgf.emitLValue(e);
181 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
184 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
185 return cgf.emitCoawaitExpr(*s).getValue();
188 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
189 return cgf.emitCoyieldExpr(*e).getValue();
192 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
193 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
197 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
198 return cgf.emitLoadOfLValue(lv, loc).getValue();
202 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
203 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
204 return cgf.emitScalarConstant(constant, e);
206 return emitLoadOfLValue(e);
209 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
211 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
215 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->
getSourceRange()),
220 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
222 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
226 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
228 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
232 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
234 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
235 "expect floating-point type");
236 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
240 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
241 mlir::Type ty = cgf.convertType(e->
getType());
244 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
245 llvm::APInt apValue(intTy.getWidth(), e->
getValue(),
247 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
248 cir::IntAttr::get(ty, apValue));
251 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
255 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
262 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
266 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
268 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
269 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
272 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
273 return cgf.emitPseudoObjectRValue(e).getValue();
275 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e);
276 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
278 auto it = e->
begin();
279 llvm::APInt value = (*it)->getValue();
280 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
283 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
285 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
289 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
292 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
293 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
296 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
297 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
300 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
301 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
304 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
305 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
308 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
309 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
312 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
314 "ScalarExprEmitter: objc availability check");
318 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
319 mlir::Value rowIdx = cgf.emitScalarExpr(e->
getRowIdx());
320 mlir::Value columnIdx = cgf.emitScalarExpr(e->
getColumnIdx());
321 mlir::Value matrix = Visit(e->
getBase());
323 if (cgf.cgm.getCodeGenOpts().OptimizationLevel > 0)
325 return builder.createMatrixExtract(loc, matrix, rowIdx, columnIdx);
328 mlir::Value VisitMatrixSingleSubscriptExpr(MatrixSingleSubscriptExpr *e) {
330 "ScalarExprEmitter: matrix singel subscript");
334 mlir::Value VisitCastExpr(
CastExpr *e);
335 mlir::Value VisitCallExpr(
const CallExpr *e);
337 mlir::Value VisitStmtExpr(StmtExpr *e) {
338 CIRGenFunction::StmtExprEvaluation eval(cgf);
346 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
348 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
352 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
353 ignoreResultAssign =
false;
359 const mlir::Value vecValue = Visit(e->
getBase());
360 const mlir::Value indexValue = Visit(e->
getIdx());
361 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
364 return emitLoadOfLValue(e);
367 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
370 mlir::Value inputVec = Visit(e->
getExpr(0));
371 mlir::Value indexVec = Visit(e->
getExpr(1));
372 return cir::VecShuffleDynamicOp::create(
373 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
376 mlir::Value vec1 = Visit(e->
getExpr(0));
377 mlir::Value vec2 = Visit(e->
getExpr(1));
382 SmallVector<mlir::Attribute, 8> indices;
385 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
391 return cir::VecShuffleOp::create(cgf.builder,
393 cgf.convertType(e->
getType()), vec1, vec2,
394 cgf.builder.getArrayAttr(indices));
397 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
400 return emitScalarConversion(Visit(e->
getSrcExpr()),
405 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
407 mlir::Value VisitMatrixElementExpr(Expr *e) {
408 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
412 mlir::Value VisitMemberExpr(MemberExpr *e);
414 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
415 return emitLoadOfLValue(e);
418 mlir::Value VisitInitListExpr(InitListExpr *e);
420 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
421 assert(cgf.getArrayInitIndex() &&
422 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
423 return cgf.getArrayInitIndex();
426 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
430 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
431 return VisitCastExpr(e);
434 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
435 return cgf.cgm.emitNullConstant(e->
getType(),
440 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
443 return cgf.getBuilder().createPtrToBoolCast(v);
446 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
447 cir::BoolType boolTy = builder.getBoolTy();
448 return cir::CastOp::create(builder, loc, boolTy,
449 cir::CastKind::float_to_bool, src);
452 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
456 if (mlir::isa<cir::BoolType>(srcVal.getType()))
464 cir::BoolType boolTy = builder.getBoolTy();
465 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
471 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
472 mlir::Location loc) {
473 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
476 return emitFloatToBoolConversion(src, loc);
478 if (llvm::isa<MemberPointerType>(srcType)) {
479 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
480 return builder.getFalse(loc);
484 return emitIntToBoolConversion(src, loc);
486 assert(::mlir::isa<cir::PointerType>(src.getType()));
487 return emitPointerToBoolConversion(src, srcType);
492 struct ScalarConversionOpts {
493 bool treatBooleanAsSigned;
494 bool emitImplicitIntegerTruncationChecks;
495 bool emitImplicitIntegerSignChangeChecks;
497 ScalarConversionOpts()
498 : treatBooleanAsSigned(
false),
499 emitImplicitIntegerTruncationChecks(
false),
500 emitImplicitIntegerSignChangeChecks(
false) {}
502 ScalarConversionOpts(clang::SanitizerSet sanOpts)
503 : treatBooleanAsSigned(
false),
504 emitImplicitIntegerTruncationChecks(
505 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
506 emitImplicitIntegerSignChangeChecks(
507 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
514 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
515 QualType dstType, mlir::Type srcTy,
516 mlir::Type dstTy, ScalarConversionOpts opts) {
518 "Internal error: matrix types not handled by this function.");
519 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
520 mlir::isa<mlir::IntegerType>(dstTy)) &&
521 "Obsolete code. Don't use mlir::IntegerType with CIR.");
523 mlir::Type fullDstTy = dstTy;
524 if (mlir::isa<cir::VectorType>(srcTy) &&
525 mlir::isa<cir::VectorType>(dstTy)) {
527 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
528 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
531 std::optional<cir::CastKind> castKind;
535 cir::FenvAttr fenvAttr;
537 if (mlir::isa<cir::BoolType>(srcTy)) {
538 if (opts.treatBooleanAsSigned)
539 cgf.getCIRGenModule().errorNYI(
"signed bool");
540 if (cgf.getBuilder().isInt(dstTy)) {
541 castKind = cir::CastKind::bool_to_int;
542 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
543 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
544 castKind = cir::CastKind::bool_to_float;
546 llvm_unreachable(
"Internal error: Cast to unexpected type");
548 }
else if (cgf.getBuilder().isInt(srcTy)) {
549 if (cgf.getBuilder().isInt(dstTy)) {
550 castKind = cir::CastKind::integral;
551 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
552 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
553 castKind = cir::CastKind::int_to_float;
554 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
555 castKind = cir::CastKind::int_to_bool;
557 llvm_unreachable(
"Internal error: Cast to unexpected type");
559 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
560 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
561 if (cgf.getBuilder().isInt(dstTy)) {
565 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
566 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
567 castKind = cir::CastKind::float_to_int;
568 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
570 return builder.createFloatingCast(src, fullDstTy);
571 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
572 castKind = cir::CastKind::float_to_bool;
574 llvm_unreachable(
"Internal error: Cast to unexpected type");
577 llvm_unreachable(
"Internal error: Cast from unexpected type");
580 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
581 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
586 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
590 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
595 "variably modified types in varargs");
598 return cgf.emitVAArg(ve);
601 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
605 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
607 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
610 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
612 return emitScalarPrePostIncDec(e, lv);
614 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
615 return VisitUnaryPrePostIncDec(e);
617 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
618 return VisitUnaryPrePostIncDec(e);
620 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
621 return VisitUnaryPrePostIncDec(e);
623 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
624 return VisitUnaryPrePostIncDec(e);
627 mlir::Value emitFixedPointIncDec(
const UnaryOperator *e, mlir::Value value,
629 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
630 if (cgf.getLangOpts().OpenMP)
638 if (
const AtomicType *atomicTy =
type->getAs<AtomicType>()) {
639 QualType valType = atomicTy->getValueType();
649 cir::IntType intTy = builder.getBoolMemoryTy();
650 mlir::Value one = builder.getConstInt(loc, intTy, 1);
651 Address intAddr = lv.getAddress().withElementType(builder, intTy);
655 cir::StoreOp store = builder.createStore(loc, one, intAddr);
656 store.setMemOrder(cir::MemOrder::SequentiallyConsistent);
657 if (lv.isVolatileQualified())
658 store.setIsVolatile(
true);
659 return builder.getTrue(loc);
662 auto xchg = cir::AtomicXchgOp::create(
664 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
665 lv.isVolatileQualified());
666 return builder.createCast(cir::CastKind::int_to_bool, xchg.getResult(),
667 builder.getBoolTy());
675 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) &&
676 cgf.getLangOpts().getSignedOverflowBehavior() !=
677 LangOptions::SOB_Trapping) {
678 mlir::Type intTy = cgf.convertType(valType);
679 mlir::Value one = builder.getConstInt(loc, intTy, 1);
680 cir::AtomicFetchKind
kind =
681 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
682 auto rmw = cir::AtomicFetchOp::create(
683 builder, loc, lv.getPointer(), one,
kind,
684 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
685 lv.isVolatileQualified(),
true);
686 mlir::Value oldVal = rmw->getResult(0);
688 return isPre ? emitIntIncOrDec(e, oldVal) : oldVal;
694 mlir::Type fpTy = cgf.convertType(valType);
695 auto fpType = mlir::cast<cir::FPTypeInterface>(fpTy);
697 if (llvm::has_single_bit(fpType.getWidth())) {
698 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
699 mlir::Value amt = builder.getConstFP(
700 loc, fpTy, llvm::APFloat(fpType.getFloatSemantics(), 1));
701 cir::AtomicFetchKind
kind =
702 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
703 auto rmw = cir::AtomicFetchOp::create(
704 builder, loc, lv.getPointer(), amt,
kind,
705 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
706 lv.isVolatileQualified(),
true);
707 mlir::Value oldVal = rmw->getResult(0);
709 return isInc ? builder.createFAdd(loc, oldVal, amt)
710 : builder.createFSub(loc, oldVal, amt);
714 "Atomic inc/dec of non-power-of-2 float");
720 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
723 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
737 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
738 }
else if (
type->isIntegerType()) {
739 QualType promotedType;
740 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
741 if (cgf.getContext().isPromotableIntegerType(
type)) {
742 promotedType = cgf.getContext().getPromotedIntegerType(
type);
743 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
744 canPerformLossyDemotionCheck =
true;
745 canPerformLossyDemotionCheck &=
746 cgf.getContext().getCanonicalType(
type) !=
747 cgf.getContext().getCanonicalType(promotedType);
748 canPerformLossyDemotionCheck &=
755 (!canPerformLossyDemotionCheck ||
756 type->isSignedIntegerOrEnumerationType() ||
758 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
759 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
760 "The following check expects that if we do promotion to different "
761 "underlying canonical type, at least one of the types (either "
762 "base or promoted) will be signed, or the bitwidths will match.");
767 value = emitIncDecConsiderOverflowBehavior(e, value);
770 value = emitIntIncOrDec(e, input,
false);
772 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
773 QualType
type = ptr->getPointeeType();
774 if (
const VariableArrayType *vla =
775 cgf.getContext().getAsVariableArrayType(
type)) {
777 mlir::Value numElts = cgf.getVLASize(vla).numElts;
779 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
781 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
786 mlir::Value amt = builder.getSInt32(amount, loc);
788 value = builder.createPtrStride(loc, value, amt);
790 }
else if (
type->isVectorType()) {
791 if (
type->hasIntegerRepresentation()) {
792 value = emitIntIncOrDec(e, input,
false);
794 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
795 value = emitFloatIncOrDec(e, input);
797 }
else if (
type->isRealFloatingType()) {
798 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
799 value = emitFloatIncOrDec(e, input);
800 }
else if (
type->isFixedPointType()) {
801 value = emitFixedPointIncDec(e, value,
type);
803 assert(
type->castAs<ObjCObjectPointerType>());
804 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
808 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
812 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
814 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
818 return e->
isPrefix() ? value : input;
821 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
823 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
824 case LangOptions::SOB_Defined:
825 return emitIntIncOrDec(e, inVal,
false);
826 case LangOptions::SOB_Undefined:
828 return emitIntIncOrDec(e, inVal,
true);
829 case LangOptions::SOB_Trapping:
831 return emitIntIncOrDec(e, inVal,
true);
832 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
835 llvm_unreachable(
"Unexpected signed overflow behavior kind");
838 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
839 if (llvm::isa<MemberPointerType>(e->
getType()))
840 return cgf.cgm.emitMemberPointerConstant(e);
842 return cgf.emitLValue(e->
getSubExpr()).getPointer();
845 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
848 return emitLoadOfLValue(e);
851 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
853 mlir::Value result = VisitUnaryPlus(e, promotionType);
854 if (result && !promotionType.
isNull())
855 return emitUnPromotedValue(result, e->
getType());
859 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
860 ignoreResultAssign =
false;
861 if (!promotionType.
isNull())
862 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
866 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
868 mlir::Value result = VisitUnaryMinus(e, promotionType);
869 if (result && !promotionType.
isNull())
870 return emitUnPromotedValue(result, e->
getType());
874 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
875 ignoreResultAssign =
false;
877 if (!promotionType.
isNull())
878 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
884 if (cir::isFPOrVectorOfFPType(operand.getType()))
885 return builder.createOrFold<cir::FNegOp>(loc, operand);
891 cgf.getLangOpts().getSignedOverflowBehavior() !=
892 LangOptions::SOB_Defined;
894 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
897 mlir::Value emitIntIncOrDec(
const UnaryOperator *e, mlir::Value input,
901 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
902 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
905 mlir::Value emitFloatIncOrDec(
const UnaryOperator *e, mlir::Value input) {
906 assert(cir::isFPOrVectorOfFPType(input.getType()) &&
907 "Expect floating-point operand");
910 if (
auto vecType = mlir::dyn_cast<cir::VectorType>(input.getType())) {
911 mlir::Type fpScalarType = vecType.getElementType();
912 auto fpInterface = mlir::cast<cir::FPTypeInterface>(fpScalarType);
913 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
915 mlir::Value amtValue = builder.getConstFP(loc, fpScalarType, amount);
916 amtValue = cir::VecSplatOp::create(builder, loc, vecType, amtValue);
917 return builder.createFAdd(loc, input, amtValue);
922 if (
type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
923 input = builder.createFloatingCast(input, builder.getSingleTy());
925 auto fpInterface = mlir::cast<cir::FPTypeInterface>(input.getType());
926 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
928 mlir::Value amtValue = builder.getConstFP(loc, input.getType(), amount);
929 mlir::Value output = builder.createFAdd(loc, input, amtValue);
931 if (
type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
932 output = builder.createFloatingCast(output, builder.getFp16Ty());
937 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
938 ignoreResultAssign =
false;
940 return builder.createOrFold<cir::NotOp>(
944 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
946 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
947 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
948 mlir::Value VisitRealImag(
const UnaryOperator *e,
949 QualType promotionType = QualType());
951 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
956 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
957 return emitLoadOfLValue(e);
959 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
960 ASTContext &ctx = cgf.getContext();
963 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
965 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
966 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
969 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
970 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
973 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
974 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
978 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
980 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
981 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
982 return cgf.emitCXXNewExpr(e);
984 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
985 cgf.emitCXXDeleteExpr(e);
988 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
994 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
999 "Expected int type for TypeTraitExpr");
1000 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
1007 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
1013 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
1015 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1018 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
1021 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
1023 "ScalarExprEmitter: cxx pseudo destructor");
1026 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
1027 cgf.emitCXXThrowExpr(e);
1031 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
1035 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
1036 QualType dstTy, mlir::Location loc);
1043 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
1045 ScalarConversionOpts opts = ScalarConversionOpts()) {
1053 cir::BoolType boolTy = builder.getBoolTy();
1054 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
1055 cir::CastKind::int_to_bool, src);
1060 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1062 llvm_unreachable(
"Unhandled scalar conversion from a fixed point type to "
1068 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1071 llvm_unreachable(
"Unhandled scalar conversion to a fixed point type from "
1077 if (srcType == dstType) {
1078 if (opts.emitImplicitIntegerSignChangeChecks)
1079 cgf.getCIRGenModule().errorNYI(loc,
1080 "implicit integer sign change checks");
1087 mlir::Type mlirSrcType = src.getType();
1092 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
1094 mlir::Type mlirDstType = cgf.convertType(dstType);
1097 !cgf.getContext().getLangOpts().NativeHalfType) {
1099 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1103 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1105 srcType = cgf.getContext().FloatTy;
1106 mlirSrcType = cgf.floatTy;
1112 if (mlirSrcType == mlirDstType) {
1113 if (opts.emitImplicitIntegerSignChangeChecks)
1114 cgf.getCIRGenModule().errorNYI(loc,
1115 "implicit integer sign change checks");
1122 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1123 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1124 return builder.getNullPtr(dstPT, src.getLoc());
1130 return builder.createPtrToInt(src, mlirDstType);
1137 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1139 "Splatted expr doesn't match with vector element type?");
1141 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1146 cgf.getCIRGenModule().errorNYI(loc,
1147 "matrix type to matrix type conversion");
1151 "Internal error: conversion between matrix type and scalar type");
1154 mlir::Value res =
nullptr;
1155 mlir::Type resTy = mlirDstType;
1157 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1159 if (mlirDstType != resTy) {
1160 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1164 if (opts.emitImplicitIntegerTruncationChecks)
1165 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1167 if (opts.emitImplicitIntegerSignChangeChecks)
1168 cgf.getCIRGenModule().errorNYI(loc,
1169 "implicit integer sign change checks");
1174 BinOpInfo emitBinOps(
const BinaryOperator *e,
1175 QualType promotionType = QualType()) {
1176 ignoreResultAssign =
false;
1178 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1179 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1180 if (!promotionType.
isNull())
1181 result.fullType = promotionType;
1183 result.fullType = e->
getType();
1184 result.compType = result.fullType;
1185 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1186 result.compType = vecType->getElementType();
1194 mlir::Value emitMul(
const BinOpInfo &ops);
1195 mlir::Value emitDiv(
const BinOpInfo &ops);
1196 mlir::Value emitRem(
const BinOpInfo &ops);
1197 mlir::Value emitAdd(
const BinOpInfo &ops);
1198 mlir::Value emitSub(
const BinOpInfo &ops);
1199 mlir::Value emitShl(
const BinOpInfo &ops);
1200 mlir::Value emitShr(
const BinOpInfo &ops);
1201 mlir::Value emitAnd(
const BinOpInfo &ops);
1202 mlir::Value emitXor(
const BinOpInfo &ops);
1203 mlir::Value emitOr(
const BinOpInfo &ops);
1205 mlir::Value emitFixedPointBinOp(
const BinOpInfo &ops);
1207 LValue emitCompoundAssignLValue(
1208 const CompoundAssignOperator *e,
1209 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1210 mlir::Value &result);
1212 emitCompoundAssign(
const CompoundAssignOperator *e,
1213 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1217 QualType getPromotionType(QualType ty) {
1218 const clang::ASTContext &ctx = cgf.getContext();
1219 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1220 QualType elementTy = complexTy->getElementType();
1226 if (
auto *vt = ty->
getAs<VectorType>()) {
1227 unsigned numElements = vt->getNumElements();
1230 return cgf.getContext().FloatTy;
1237#define HANDLEBINOP(OP) \
1238 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1239 QualType promotionTy = getPromotionType(e->getType()); \
1240 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1241 if (result && !promotionTy.isNull()) \
1242 result = emitUnPromotedValue(result, e->getType()); \
1245 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1246 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1264 return cir::CmpOpKind::lt;
1266 return cir::CmpOpKind::gt;
1268 return cir::CmpOpKind::le;
1270 return cir::CmpOpKind::ge;
1272 return cir::CmpOpKind::eq;
1274 return cir::CmpOpKind::ne;
1276 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1280 mlir::Value emitCmp(
const BinaryOperator *e) {
1281 ignoreResultAssign =
false;
1282 const mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1288 if (lhsTy->
getAs<MemberPointerType>()) {
1291 mlir::Value lhs = cgf.emitScalarExpr(e->
getLHS());
1292 mlir::Value rhs = cgf.emitScalarExpr(e->
getRHS());
1293 result = builder.createCompare(loc,
kind, lhs, rhs);
1295 BinOpInfo boInfo = emitBinOps(e);
1296 mlir::Value lhs = boInfo.lhs;
1297 mlir::Value rhs = boInfo.rhs;
1303 cgf.cgm.errorNYI(loc,
"AltiVec comparison");
1307 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1308 cgf.convertType(boInfo.fullType),
kind,
1309 boInfo.lhs, boInfo.rhs);
1311 }
else if (boInfo.isFixedPointOp()) {
1312 result = emitFixedPointBinOp(boInfo);
1315 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1316 mlir::isa<cir::PointerType>(lhs.getType()) &&
1317 mlir::isa<cir::PointerType>(rhs.getType())) {
1318 cgf.cgm.errorNYI(loc,
"strict vtable pointer comparisons");
1320 result = builder.createCompare(loc,
kind, lhs, rhs);
1324 "Complex Comparison: can only be an equality comparison");
1328 lhs = cgf.emitComplexExpr(e->
getLHS());
1330 mlir::Value lhsReal = Visit(e->
getLHS());
1331 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1332 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1337 rhs = cgf.emitComplexExpr(e->
getRHS());
1339 mlir::Value rhsReal = Visit(e->
getRHS());
1340 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1341 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1344 result = builder.createCompare(loc,
kind, lhs, rhs);
1347 return emitScalarConversion(result, cgf.getContext().BoolTy, e->
getType(),
1352#define VISITCOMP(CODE) \
1353 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1363 const bool ignore = std::exchange(ignoreResultAssign,
false);
1378 rhs = Visit(e->
getRHS());
1388 if (lhs.isBitField()) {
1408 if (!lhs.isVolatile())
1412 return emitLoadOfLValue(lhs, e->
getExprLoc());
1415 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1416 cgf.emitIgnoredExpr(e->
getLHS());
1418 return Visit(e->
getRHS());
1421 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1423 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1425 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1427 mlir::Value lhs = Visit(e->
getLHS());
1428 mlir::Value rhs = Visit(e->
getRHS());
1430 auto cmpOpKind = cir::CmpOpKind::ne;
1432 mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1433 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1434 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1435 return builder.createAnd(loc, lhs, rhs);
1439 mlir::Type resTy = cgf.convertType(e->
getType());
1440 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1442 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1444 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1446 auto resOp = cir::TernaryOp::create(
1447 builder, loc, lhsCondV,
1448 [&](mlir::OpBuilder &b, mlir::Location loc) {
1449 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1450 b.getInsertionBlock()};
1451 cgf.curLexScope->setAsTernary();
1452 eval.beginEvaluation();
1453 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1454 eval.endEvaluation();
1456 cir::YieldOp::create(b, loc, res);
1459 [&](mlir::OpBuilder &b, mlir::Location loc) {
1460 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1461 b.getInsertionBlock()};
1463 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1464 cir::YieldOp::create(b, loc, res.getRes());
1466 return maybePromoteBoolResult(resOp.getResult(), resTy);
1469 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1471 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1473 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1475 mlir::Value lhs = Visit(e->
getLHS());
1476 mlir::Value rhs = Visit(e->
getRHS());
1478 auto cmpOpKind = cir::CmpOpKind::ne;
1480 mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1481 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1482 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1483 return builder.createOr(loc, lhs, rhs);
1487 mlir::Type resTy = cgf.convertType(e->
getType());
1488 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1490 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1492 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1494 auto resOp = cir::TernaryOp::create(
1495 builder, loc, lhsCondV,
1496 [&](mlir::OpBuilder &b, mlir::Location loc) {
1497 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1498 b.getInsertionBlock()};
1500 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1501 cir::YieldOp::create(b, loc, res.getRes());
1504 [&](mlir::OpBuilder &b, mlir::Location loc) {
1505 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1506 b.getInsertionBlock()};
1508 eval.beginEvaluation();
1509 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1510 eval.endEvaluation();
1512 cir::YieldOp::create(b, loc, res);
1515 return maybePromoteBoolResult(resOp.getResult(), resTy);
1518 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1519 return emitLoadOfLValue(e);
1522 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1523 return emitLoadOfLValue(e);
1527 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1528 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1532 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1536 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1538 "ScalarExprEmitter: objc string literal");
1541 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1542 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1545 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1547 "ScalarExprEmitter: objc array literal");
1550 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1552 "ScalarExprEmitter: objc dictionary literal");
1556 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1557 mlir::Value src,
unsigned numElementsDst) {
1558 static constexpr int64_t mask[] = {0, 1, 2, -1};
1559 return builder.createVecShuffle(
1560 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1582 mlir::Type srcTy = src.getType();
1586 return builder.createBitcast(src, dstTy);
1591 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1599 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1603 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1610 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1614 return builder.createIntToPtr(src, dstTy);
1617 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1618 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1619 mlir::Type srcTy = src.getType();
1620 mlir::Type dstTy = cgf.convertType(e->
getType());
1632 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1638 if (numElementsSrc == 3 && numElementsDst != 3) {
1640 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1641 "numElemsDst != 3");
1648 if (numElementsSrc != 3 && numElementsDst == 3) {
1649 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1651 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1653 src = convertVec3AndVec4(builder, loc, src, 3);
1660 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1661 return cgf.emitAtomicExpr(e).getValue();
1665LValue ScalarExprEmitter::emitCompoundAssignLValue(
1667 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1668 mlir::Value &result) {
1679 if (promotionTypeCR.
isNull())
1683 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1685 if (!promotionTypeRHS.
isNull())
1688 opInfo.rhs = Visit(e->
getRHS());
1690 opInfo.fullType = promotionTypeCR;
1691 opInfo.compType = opInfo.fullType;
1692 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1693 opInfo.compType = vecType->getElementType();
1702 if (lhsTy->
getAs<AtomicType>()) {
1703 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1707 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1709 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
1711 if (!promotionTypeLHS.
isNull())
1712 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1714 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1718 result = (this->*func)(opInfo);
1722 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1723 ScalarConversionOpts(cgf.
sanOpts));
1729 if (lhsLV.isBitField())
1740mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1744 cir::CastKind castOpKind;
1746 case CK_FloatingComplexToReal:
1747 castOpKind = cir::CastKind::float_complex_to_real;
1749 case CK_IntegralComplexToReal:
1750 castOpKind = cir::CastKind::int_complex_to_real;
1752 case CK_FloatingComplexToBoolean:
1753 castOpKind = cir::CastKind::float_complex_to_bool;
1755 case CK_IntegralComplexToBoolean:
1756 castOpKind = cir::CastKind::int_complex_to_bool;
1759 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1765mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1766 QualType promotionType) {
1768 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1769 switch (bo->getOpcode()) {
1770#define HANDLE_BINOP(OP) \
1772 return emit##OP(emitBinOps(bo, promotionType));
1781 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1782 switch (uo->getOpcode()) {
1785 return VisitRealImag(uo, promotionType);
1787 return VisitUnaryMinus(uo, promotionType);
1789 return VisitUnaryPlus(uo, promotionType);
1794 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1796 if (!promotionType.
isNull())
1797 return emitPromotedValue(result, promotionType);
1798 return emitUnPromotedValue(result, e->
getType());
1803mlir::Value ScalarExprEmitter::emitCompoundAssign(
1804 const CompoundAssignOperator *e,
1805 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1807 bool ignore = std::exchange(ignoreResultAssign,
false);
1809 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1820 if (!lhs.isVolatile())
1824 return emitLoadOfLValue(lhs, e->
getExprLoc());
1828ScalarExprEmitter::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
1831 cir::GlobalOp globalConstStr =
1837 auto exprTy = mlir::cast<cir::PointerType>(convertType(e->
getType()));
1838 auto addrTy = mlir::cast<cir::PointerType>(addr.getType());
1839 if (addrTy.getAddrSpace() != exprTy.getAddrSpace())
1841 addr, builder.
getPointerTo(addrTy.getPointee(), exprTy.getAddrSpace()));
1845mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1846 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1861#define COMPOUND_OP(Op) \
1862 case BO_##Op##Assign: \
1863 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1900 llvm_unreachable(
"Not valid compound assignment operators");
1902 llvm_unreachable(
"Unhandled compound assignment operator");
1907 bool ignoreResultAssign) {
1909 "Invalid scalar expression to emit");
1912 .Visit(
const_cast<Expr *
>(e));
1917 if (!promotionType.
isNull())
1932static std::optional<QualType>
1936 return std::nullopt;
1941 return std::nullopt;
1954 const BinOpInfo &op) {
1956 "Expected a unary or binary operator");
1960 if (!op.mayHaveIntegerOverflow())
1964 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1965 return !uo->canOverflow();
1970 std::optional<QualType> optionalLHSTy =
1975 std::optional<QualType> optionalRHSTy =
1985 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1992 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1993 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1998 const BinOpInfo &op,
1999 bool isSubtraction) {
2004 mlir::Value pointer = op.lhs;
2005 Expr *pointerOperand =
expr->getLHS();
2006 mlir::Value
index = op.rhs;
2007 Expr *indexOperand =
expr->getRHS();
2013 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
2014 std::swap(pointer,
index);
2015 std::swap(pointerOperand, indexOperand);
2017 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
2018 "Need a pointer operand");
2019 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
2054 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
2064 numElements.getType());
2075 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
2080 return cir::PtrStrideOp::create(cgf.
getBuilder(),
2082 pointer.getType(), pointer,
index);
2086 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
2087 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
2097 bool negMul,
bool negAdd) {
2098 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
2099 mlir::Value mulOp0 = mulOp.getLhs();
2100 mlir::Value mulOp1 = mulOp.getRhs();
2108 mlir::Value fmuladd =
2109 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
2110 addend, mulOp.getFenvAttr());
2123 bool isSub =
false) {
2124 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2125 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2126 "Only fadd/fsub can be the root of an fmuladd.");
2133 mlir::Value lhs = op.lhs;
2134 mlir::Value rhs = op.rhs;
2138 bool negLHS =
false;
2139 if (
auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2140 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2141 lhs = lhsNeg.getInput();
2146 bool negRHS =
false;
2147 if (
auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2148 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2149 rhs = rhsNeg.getInput();
2157 if (
auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2158 if (lhsMul.getResult().use_empty() || negLHS) {
2161 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2162 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2165 if (
auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2166 if (rhsMul.getResult().use_empty() || negRHS) {
2169 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2170 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS,
false);
2177mlir::Value ScalarExprEmitter::emitFixedPointIncDec(
const UnaryOperator *e,
2196 if (
type->isSignedFixedPointType()) {
2203 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(
info.loc));
2206 fpbuilder.createIntegerToFixed(
info.rhs,
true, dstSema);
2207 return emitFixedPointBinOp(info);
2210mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2213 mlir::Location loc) {
2216 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2220 result = fpBuilder.createFloatingToFixed(
2224 result = fpBuilder.createFixedToFloating(
2228 llvm::FixedPointSemantics srcFPSema =
2230 llvm::FixedPointSemantics dstFPSema =
2234 result = fpBuilder.createFixedToInteger(
2235 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2238 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2241 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2247mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
2248 const mlir::Location loc = cgf.
getLoc(ops.loc);
2251 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2252 case LangOptions::SOB_Defined:
2253 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2254 return builder.
createMul(loc, ops.lhs, ops.rhs);
2256 case LangOptions::SOB_Undefined:
2257 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2260 case LangOptions::SOB_Trapping:
2268 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2276 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2278 return builder.
createMul(loc, lhs, rhs);
2282 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2284 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2286 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2287 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2288 return builder.
createFMul(loc, ops.lhs, ops.rhs);
2291 if (ops.isFixedPointOp())
2292 return emitFixedPointBinOp(ops);
2294 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2297mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2298 const mlir::Location loc = cgf.
getLoc(ops.loc);
2299 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2300 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2301 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2305 assert(mlir::isa<cir::MatrixType>(ops.lhs.getType()) &&
2306 "first operand must be a matrix");
2307 assert(cir::isAnyIntegerOrFloatingPointType(ops.rhs.getType()) &&
2308 "second operand must be an arithmetic type");
2313 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2314 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2316 return builder.
createDiv(loc, lhs, rhs);
2319 if (ops.isFixedPointOp())
2320 return emitFixedPointBinOp(ops);
2322 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2325mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2326 const mlir::Location loc = cgf.
getLoc(ops.loc);
2327 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2328 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2329 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2331 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2335mlir::Value ScalarExprEmitter::emitFixedPointBinOp(
const BinOpInfo &ops) {
2340 QualType resultTy = ops.compType;
2341 QualType lhsTy, rhsTy;
2342 if (
const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2343 rhsTy = binOp->getRHS()->getType();
2344 if (
const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2349 lhsTy = cao->getComputationLHSType();
2350 resultTy = cao->getComputationResultType();
2352 lhsTy = binOp->getLHS()->getType();
2354 }
else if (
const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2355 lhsTy = unOp->getSubExpr()->getType();
2356 rhsTy = unOp->getSubExpr()->getType();
2359 mlir::Value lhs = ops.lhs;
2360 mlir::Value rhs = ops.rhs;
2365 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2369 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(ops.loc));
2370 switch (ops.opcode) {
2373 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2377 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2381 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2385 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2389 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2393 result = fpbuilder.createShr(lhs, rhs);
2401 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2402 clangCmpToCIRCmp(ops.opcode));
2406 llvm_unreachable(
"Found unimplemented fixed point binary operation");
2420 "Found unsupported binary operation for fixed point types.");
2426 return fpbuilder.createFixedToFixed(
2427 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2430mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2431 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2432 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2436 const mlir::Location loc = cgf.
getLoc(ops.loc);
2439 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2440 case LangOptions::SOB_Defined:
2441 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2442 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2444 case LangOptions::SOB_Undefined:
2445 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2448 case LangOptions::SOB_Trapping:
2460 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2461 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2463 return builder.
createAdd(loc, lhs, rhs);
2467 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2469 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2471 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2472 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2476 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2479 if (ops.isFixedPointOp())
2480 return emitFixedPointBinOp(ops);
2482 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2485mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2486 const mlir::Location loc = cgf.
getLoc(ops.loc);
2488 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2491 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2492 case LangOptions::SOB_Defined: {
2493 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2494 return builder.
createSub(loc, ops.lhs, ops.rhs);
2497 case LangOptions::SOB_Undefined:
2498 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2501 case LangOptions::SOB_Trapping:
2514 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2515 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2517 return builder.
createSub(loc, lhs, rhs);
2521 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2523 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2525 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2526 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2528 if (mlir::Value fmuladd =
2531 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2534 if (ops.isFixedPointOp())
2535 return emitFixedPointBinOp(ops);
2537 return builder.
createSub(loc, ops.lhs, ops.rhs);
2542 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2554 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2558mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2560 if (ops.isFixedPointOp())
2561 return emitFixedPointBinOp(ops);
2567 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2571 bool sanitizeUnsignedBase =
2572 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2574 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2575 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2580 else if ((sanitizeBase || sanitizeExponent) &&
2581 mlir::isa<cir::IntType>(ops.lhs.getType()))
2587mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2589 if (ops.isFixedPointOp())
2590 return emitFixedPointBinOp(ops);
2599 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2600 mlir::isa<cir::IntType>(ops.lhs.getType()))
2608mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2609 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2611mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2612 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2614mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2615 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2622mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2624 QualType destTy = ce->
getType();
2626 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2630 ignoreResultAssign =
false;
2633 case clang::CK_Dependent:
2634 llvm_unreachable(
"dependent cast kind in CIR gen!");
2635 case clang::CK_BuiltinFnToFnPtr:
2636 llvm_unreachable(
"builtin functions are handled elsewhere");
2637 case CK_LValueBitCast:
2638 case CK_LValueToRValueBitCast: {
2640 Address sourceAddr = sourceLVal.getAddress();
2646 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2649 case CK_CPointerToObjCPointerCast:
2650 case CK_BlockPointerToObjCPointerCast:
2651 case CK_AnyPointerToBlockPointerCast:
2653 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2658 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2660 "sanitizer support");
2664 "strict vtable pointers");
2690 case CK_AddressSpaceConversion: {
2691 Expr::EvalResult result;
2700 mlir::cast<cir::PointerType>(convertType(destTy)), destTy,
2706 case CK_AtomicToNonAtomic:
2707 case CK_NonAtomicToAtomic:
2708 case CK_UserDefinedConversion:
2709 return Visit(
const_cast<Expr *
>(subExpr));
2713 case CK_IntegralToPointer: {
2715 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2724 : cir::CastKind::integral,
2729 "IntegralToPointer: strict vtable pointers");
2736 case CK_BaseToDerived: {
2738 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2750 case CK_UncheckedDerivedToBase:
2751 case CK_DerivedToBase: {
2762 case CK_ArrayToPointerDecay:
2765 case CK_NullToPointer: {
2771 auto ty = mlir::cast<cir::PointerType>(cgf.
convertType(destTy));
2776 case CK_NullToMemberPointer: {
2782 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2788 case CK_ReinterpretMemberPointer: {
2789 mlir::Value src = Visit(subExpr);
2793 case CK_BaseToDerivedMemberPointer:
2794 case CK_DerivedToBaseMemberPointer: {
2795 mlir::Value src = Visit(subExpr);
2799 QualType derivedTy =
2800 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2801 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2802 NestedNameSpecifier qualifier = mpType->getQualifier();
2803 assert(qualifier &&
"member pointer without class qualifier");
2804 const Type *qualifierType = qualifier.getAsType();
2805 assert(qualifierType &&
"member pointer qualifier is not a type");
2812 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2815 if (
kind == CK_BaseToDerivedMemberPointer)
2816 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2818 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2821 if (
kind == CK_BaseToDerivedMemberPointer)
2822 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2824 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2828 case CK_LValueToRValue:
2830 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2831 return Visit(
const_cast<Expr *
>(subExpr));
2833 case CK_IntegralCast: {
2834 ScalarConversionOpts opts;
2835 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2836 if (!ice->isPartOfExplicitCast())
2837 opts = ScalarConversionOpts(cgf.
sanOpts);
2839 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2843 case CK_FloatingComplexToReal:
2844 case CK_IntegralComplexToReal:
2845 case CK_FloatingComplexToBoolean:
2846 case CK_IntegralComplexToBoolean: {
2852 case CK_FloatingRealToComplex:
2853 case CK_FloatingComplexCast:
2854 case CK_IntegralRealToComplex:
2855 case CK_IntegralComplexCast:
2856 case CK_IntegralComplexToFloatingComplex:
2857 case CK_FloatingComplexToIntegralComplex:
2858 llvm_unreachable(
"scalar cast to non-scalar value");
2860 case CK_PointerToIntegral: {
2861 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2864 "strict vtable pointers");
2871 case CK_FixedPointCast:
2872 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2875 case CK_FixedPointToBoolean:
2877 "Expected src type to be fixed point type");
2878 assert(destTy->
isBooleanType() &&
"Expected dest type to be boolean type");
2879 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2882 case CK_FixedPointToIntegral:
2884 "Expected src type to be fixed point type");
2885 assert(destTy->
isIntegerType() &&
"Expected dest type to be an integer");
2886 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2889 case CK_IntegralToFixedPoint:
2891 "Expected src type to be an integer");
2893 "Expected dest type to be fixed point type");
2894 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2897 case CK_IntegralToFloating:
2898 case CK_FloatingToIntegral:
2899 case CK_FloatingCast:
2900 case CK_FixedPointToFloating:
2901 case CK_FloatingToFixedPoint: {
2902 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2903 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2907 case CK_IntegralToBoolean:
2908 return emitIntToBoolConversion(Visit(subExpr),
2911 case CK_PointerToBoolean:
2912 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2913 case CK_FloatingToBoolean:
2914 return emitFloatToBoolConversion(Visit(subExpr),
2916 case CK_MemberPointerToBoolean: {
2917 mlir::Value memPtr = Visit(subExpr);
2919 cir::CastKind::member_ptr_to_bool, memPtr,
2923 case CK_VectorSplat: {
2926 assert(mlir::isa<cir::VectorType>(destCIRTy) &&
2927 "CK_VectorSplat to non-vector type");
2928 return cir::VecSplatOp::create(builder,
2930 destCIRTy, Visit(subExpr));
2932 case CK_FunctionToPointerDecay:
2942mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2944 return emitLoadOfLValue(e);
2951mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2956 Expr::EvalResult result;
2958 llvm::APSInt value = result.
Val.
getInt();
2968 return builder.
getBool(value.getBoolValue(), loc);
2973 return emitLoadOfLValue(e);
2976mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2977 const unsigned numInitElements = e->
getNumInits();
2979 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2980 assert((ignore ==
false ||
2982 "init list ignored");
2990 const auto vectorType =
2993 SmallVector<mlir::Value, 16> elements;
2994 for (Expr *init : e->
inits()) {
2995 elements.push_back(Visit(init));
2999 if (numInitElements < vectorType.getSize()) {
3002 std::fill_n(std::back_inserter(elements),
3003 vectorType.getSize() - numInitElements, zeroValue);
3006 return cir::VecCreateOp::create(cgf.
getBuilder(),
3015 if (numInitElements == 0)
3026 "Invalid scalar expression to emit");
3028 .emitScalarConversion(src, srcTy, dstTy, loc);
3036 "Invalid complex -> scalar conversion");
3041 ? cir::CastKind::float_complex_to_bool
3042 : cir::CastKind::int_complex_to_bool;
3047 ? cir::CastKind::float_complex_to_real
3048 : cir::CastKind::int_complex_to_real;
3054mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
3061 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
3062 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
3078mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
3083 llvm::APSInt value = evalResult.
Val.
getInt();
3089 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
3093mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
3095 mlir::Value result = VisitRealImag(e, promotionTy);
3096 if (result && !promotionTy.
isNull())
3097 result = emitUnPromotedValue(result, e->
getType());
3101mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
3103 mlir::Value result = VisitRealImag(e, promotionTy);
3104 if (result && !promotionTy.
isNull())
3105 result = emitUnPromotedValue(result, e->
getType());
3109mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
3110 QualType promotionTy) {
3113 "Invalid UnaryOp kind for ComplexType Real or Imag");
3135 mlir::Value operand = promotionTy.
isNull()
3137 : cgf.emitPromotedScalarExpr(op, promotionTy);
3143 mlir::Value operand;
3146 operand = cir::LoadOp::create(builder, loc, operand);
3147 }
else if (!promotionTy.
isNull()) {
3157mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
3158 const UnaryExprOrTypeTraitExpr *e) {
3162 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
3163 if (
const VariableArrayType *vat =
3168 bool evaluateExtent =
true;
3169 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3171 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
3174 if (evaluateExtent) {
3185 if (
kind == UETT_CountOf)
3190 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
3191 mlir::Value numElts = vlaSize.
numElts;
3195 if (!eltSize.
isOne()) {
3197 mlir::Value eltSizeValue =
3200 return builder.
createMul(loc, eltSizeValue, numElts,
3207 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
3214 }
else if (e->
getKind() == UETT_VectorElements) {
3216 if (vecTy.getIsScalable()) {
3219 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3226 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getSize()));
3236mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3237 const AbstractConditionalOperator *e) {
3240 ignoreResultAssign =
false;
3243 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3245 Expr *condExpr = e->
getCond();
3253 Expr *live = lhsExpr, *dead = rhsExpr;
3255 std::swap(live, dead);
3261 mlir::Value result = Visit(live);
3268 loc, cir::PoisonAttr::get(builder.getContext(),
3276 QualType condType = condExpr->
getType();
3285 mlir::Value lhsValue = Visit(lhsExpr);
3286 mlir::Value rhsValue = Visit(rhsExpr);
3288 mlir::Type vecTy = convertType(condType);
3289 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
3290 auto testMSB = cir::VecCmpOp::create(
3291 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3293 mlir::Value tmp2 = builder.
createNot(tmp);
3296 mlir::Value rhsTmp = rhsValue;
3297 mlir::Value lhsTmp = lhsValue;
3298 bool wasCast =
false;
3300 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
3306 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
3307 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
3308 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
3317 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
3321 mlir::Value condValue = Visit(condExpr);
3322 mlir::Value lhsValue = Visit(lhsExpr);
3323 mlir::Value rhsValue = Visit(rhsExpr);
3324 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3338 mlir::Value lhs = Visit(lhsExpr);
3339 mlir::Value rhs = Visit(rhsExpr);
3342 assert(!rhs &&
"lhs and rhs types must match");
3350 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
3352 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
3353 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3360 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3362 eval.beginEvaluation();
3363 branch = Visit(
expr);
3364 eval.endEvaluation();
3365 branchCleanups.forceCleanup({&branch});
3369 cir::YieldOp::create(b, loc, branch);
3372 cir::TernaryOp ternary = cir::TernaryOp::create(
3373 builder, loc, condV,
3375 [&](mlir::OpBuilder &b, mlir::Location loc) {
3376 emitBranch(b, loc, lhsExpr);
3379 [&](mlir::OpBuilder &b, mlir::Location loc) {
3380 emitBranch(b, loc, rhsExpr);
3385 for (mlir::Region *region :
3386 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3387 mlir::Block &lastBlock = region->back();
3388 if (lastBlock.empty() ||
3389 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3390 mlir::OpBuilder::InsertionGuard guard(builder);
3391 builder.setInsertionPointToEnd(&lastBlock);
3392 cir::YieldOp::create(builder, loc);
3396 return ternary.getResult();
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)
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 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.
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)
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
friend class ::ScalarExprEmitter
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
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 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)
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool emitMatrixIndexAssumption()
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.