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) {
277 "ScalarExprEmitter: sycl unique stable name");
280 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
282 auto it = e->
begin();
283 llvm::APInt value = (*it)->getValue();
284 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
287 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
289 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
293 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
296 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
297 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
300 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
301 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
304 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
305 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
308 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
309 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
312 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
313 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
316 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
318 "ScalarExprEmitter: objc availability check");
322 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
324 "ScalarExprEmitter: matrix subscript");
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 ? emitIncOrDec(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 = emitIncOrDec(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 = emitIncOrDec(e, input,
false);
794 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec vector of float");
797 }
else if (
type->isRealFloatingType()) {
798 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
800 if (
type->isHalfType() &&
801 !cgf.getContext().getLangOpts().NativeHalfType) {
806 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
808 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
809 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
810 mlir::Value amount = builder.getConstFP(
811 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
812 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
813 : builder.createFSub(loc, value, amount);
815 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
818 }
else if (
type->isFixedPointType()) {
819 value = emitFixedPointIncDec(e, value,
type);
821 assert(
type->castAs<ObjCObjectPointerType>());
822 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
826 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
830 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
832 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
836 return e->
isPrefix() ? value : input;
839 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
841 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
842 case LangOptions::SOB_Defined:
843 return emitIncOrDec(e, inVal,
false);
844 case LangOptions::SOB_Undefined:
846 return emitIncOrDec(e, inVal,
true);
847 case LangOptions::SOB_Trapping:
849 return emitIncOrDec(e, inVal,
true);
850 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
853 llvm_unreachable(
"Unexpected signed overflow behavior kind");
856 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
857 if (llvm::isa<MemberPointerType>(e->
getType()))
858 return cgf.cgm.emitMemberPointerConstant(e);
860 return cgf.emitLValue(e->
getSubExpr()).getPointer();
863 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
866 return emitLoadOfLValue(e);
869 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
871 mlir::Value result = VisitUnaryPlus(e, promotionType);
872 if (result && !promotionType.
isNull())
873 return emitUnPromotedValue(result, e->
getType());
877 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
878 ignoreResultAssign =
false;
879 if (!promotionType.
isNull())
880 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
884 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
886 mlir::Value result = VisitUnaryMinus(e, promotionType);
887 if (result && !promotionType.
isNull())
888 return emitUnPromotedValue(result, e->
getType());
892 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
893 ignoreResultAssign =
false;
895 if (!promotionType.
isNull())
896 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
902 if (cir::isFPOrVectorOfFPType(operand.getType()))
903 return builder.createOrFold<cir::FNegOp>(loc, operand);
909 cgf.getLangOpts().getSignedOverflowBehavior() !=
910 LangOptions::SOB_Defined;
912 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
915 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
919 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
920 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
923 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
924 ignoreResultAssign =
false;
926 return builder.createOrFold<cir::NotOp>(
930 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
932 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
933 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
934 mlir::Value VisitRealImag(
const UnaryOperator *e,
935 QualType promotionType = QualType());
937 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
942 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
943 return emitLoadOfLValue(e);
945 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
946 ASTContext &ctx = cgf.getContext();
949 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
951 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
952 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
955 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
956 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
959 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
960 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
964 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
966 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
967 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
968 return cgf.emitCXXNewExpr(e);
970 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
971 cgf.emitCXXDeleteExpr(e);
974 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
980 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
985 "Expected int type for TypeTraitExpr");
986 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
993 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
999 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
1001 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1004 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
1007 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
1009 "ScalarExprEmitter: cxx pseudo destructor");
1012 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
1013 cgf.emitCXXThrowExpr(e);
1017 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
1021 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
1022 QualType dstTy, mlir::Location loc);
1029 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
1031 ScalarConversionOpts opts = ScalarConversionOpts()) {
1039 cir::BoolType boolTy = builder.getBoolTy();
1040 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
1041 cir::CastKind::int_to_bool, src);
1046 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1048 llvm_unreachable(
"Unhandled scalar conversion from a fixed point type to "
1054 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1057 llvm_unreachable(
"Unhandled scalar conversion to a fixed point type from "
1063 if (srcType == dstType) {
1064 if (opts.emitImplicitIntegerSignChangeChecks)
1065 cgf.getCIRGenModule().errorNYI(loc,
1066 "implicit integer sign change checks");
1073 mlir::Type mlirSrcType = src.getType();
1078 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
1080 mlir::Type mlirDstType = cgf.convertType(dstType);
1083 !cgf.getContext().getLangOpts().NativeHalfType) {
1085 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1089 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1091 srcType = cgf.getContext().FloatTy;
1092 mlirSrcType = cgf.floatTy;
1098 if (mlirSrcType == mlirDstType) {
1099 if (opts.emitImplicitIntegerSignChangeChecks)
1100 cgf.getCIRGenModule().errorNYI(loc,
1101 "implicit integer sign change checks");
1108 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1109 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1110 return builder.getNullPtr(dstPT, src.getLoc());
1116 return builder.createPtrToInt(src, mlirDstType);
1123 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1125 "Splatted expr doesn't match with vector element type?");
1127 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1132 cgf.getCIRGenModule().errorNYI(loc,
1133 "matrix type to matrix type conversion");
1137 "Internal error: conversion between matrix type and scalar type");
1140 mlir::Value res =
nullptr;
1141 mlir::Type resTy = mlirDstType;
1143 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1145 if (mlirDstType != resTy) {
1146 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1150 if (opts.emitImplicitIntegerTruncationChecks)
1151 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1153 if (opts.emitImplicitIntegerSignChangeChecks)
1154 cgf.getCIRGenModule().errorNYI(loc,
1155 "implicit integer sign change checks");
1160 BinOpInfo emitBinOps(
const BinaryOperator *e,
1161 QualType promotionType = QualType()) {
1162 ignoreResultAssign =
false;
1164 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1165 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1166 if (!promotionType.
isNull())
1167 result.fullType = promotionType;
1169 result.fullType = e->
getType();
1170 result.compType = result.fullType;
1171 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1172 result.compType = vecType->getElementType();
1180 mlir::Value emitMul(
const BinOpInfo &ops);
1181 mlir::Value emitDiv(
const BinOpInfo &ops);
1182 mlir::Value emitRem(
const BinOpInfo &ops);
1183 mlir::Value emitAdd(
const BinOpInfo &ops);
1184 mlir::Value emitSub(
const BinOpInfo &ops);
1185 mlir::Value emitShl(
const BinOpInfo &ops);
1186 mlir::Value emitShr(
const BinOpInfo &ops);
1187 mlir::Value emitAnd(
const BinOpInfo &ops);
1188 mlir::Value emitXor(
const BinOpInfo &ops);
1189 mlir::Value emitOr(
const BinOpInfo &ops);
1191 mlir::Value emitFixedPointBinOp(
const BinOpInfo &ops);
1193 LValue emitCompoundAssignLValue(
1194 const CompoundAssignOperator *e,
1195 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1196 mlir::Value &result);
1198 emitCompoundAssign(
const CompoundAssignOperator *e,
1199 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1203 QualType getPromotionType(QualType ty) {
1204 const clang::ASTContext &ctx = cgf.getContext();
1205 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1206 QualType elementTy = complexTy->getElementType();
1212 if (
auto *vt = ty->
getAs<VectorType>()) {
1213 unsigned numElements = vt->getNumElements();
1216 return cgf.getContext().FloatTy;
1223#define HANDLEBINOP(OP) \
1224 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1225 QualType promotionTy = getPromotionType(e->getType()); \
1226 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1227 if (result && !promotionTy.isNull()) \
1228 result = emitUnPromotedValue(result, e->getType()); \
1231 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1232 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1250 return cir::CmpOpKind::lt;
1252 return cir::CmpOpKind::gt;
1254 return cir::CmpOpKind::le;
1256 return cir::CmpOpKind::ge;
1258 return cir::CmpOpKind::eq;
1260 return cir::CmpOpKind::ne;
1262 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1266 mlir::Value emitCmp(
const BinaryOperator *e) {
1267 ignoreResultAssign =
false;
1268 const mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1274 if (lhsTy->
getAs<MemberPointerType>()) {
1277 mlir::Value lhs = cgf.emitScalarExpr(e->
getLHS());
1278 mlir::Value rhs = cgf.emitScalarExpr(e->
getRHS());
1279 result = builder.createCompare(loc,
kind, lhs, rhs);
1281 BinOpInfo boInfo = emitBinOps(e);
1282 mlir::Value lhs = boInfo.lhs;
1283 mlir::Value rhs = boInfo.rhs;
1289 cgf.cgm.errorNYI(loc,
"AltiVec comparison");
1293 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1294 cgf.convertType(boInfo.fullType),
kind,
1295 boInfo.lhs, boInfo.rhs);
1297 }
else if (boInfo.isFixedPointOp()) {
1298 result = emitFixedPointBinOp(boInfo);
1301 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1302 mlir::isa<cir::PointerType>(lhs.getType()) &&
1303 mlir::isa<cir::PointerType>(rhs.getType())) {
1304 cgf.cgm.errorNYI(loc,
"strict vtable pointer comparisons");
1306 result = builder.createCompare(loc,
kind, lhs, rhs);
1310 "Complex Comparison: can only be an equality comparison");
1314 lhs = cgf.emitComplexExpr(e->
getLHS());
1316 mlir::Value lhsReal = Visit(e->
getLHS());
1317 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1318 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1323 rhs = cgf.emitComplexExpr(e->
getRHS());
1325 mlir::Value rhsReal = Visit(e->
getRHS());
1326 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1327 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1330 result = builder.createCompare(loc,
kind, lhs, rhs);
1333 return emitScalarConversion(result, cgf.getContext().BoolTy, e->
getType(),
1338#define VISITCOMP(CODE) \
1339 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1349 const bool ignore = std::exchange(ignoreResultAssign,
false);
1364 rhs = Visit(e->
getRHS());
1374 if (lhs.isBitField()) {
1394 if (!lhs.isVolatile())
1398 return emitLoadOfLValue(lhs, e->
getExprLoc());
1401 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1402 cgf.emitIgnoredExpr(e->
getLHS());
1404 return Visit(e->
getRHS());
1407 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1409 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1411 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1413 mlir::Value lhs = Visit(e->
getLHS());
1414 mlir::Value rhs = Visit(e->
getRHS());
1416 auto cmpOpKind = cir::CmpOpKind::ne;
1417 lhs = builder.createVecCompare(loc, cmpOpKind, lhs, zeroVec);
1418 rhs = builder.createVecCompare(loc, cmpOpKind, rhs, zeroVec);
1419 return builder.createAnd(loc, lhs, rhs);
1423 mlir::Type resTy = cgf.convertType(e->
getType());
1424 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1426 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1428 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1430 auto resOp = cir::TernaryOp::create(
1431 builder, loc, lhsCondV,
1432 [&](mlir::OpBuilder &b, mlir::Location loc) {
1433 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1434 b.getInsertionBlock()};
1435 cgf.curLexScope->setAsTernary();
1436 eval.beginEvaluation();
1437 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1438 eval.endEvaluation();
1440 cir::YieldOp::create(b, loc, res);
1443 [&](mlir::OpBuilder &b, mlir::Location loc) {
1444 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1445 b.getInsertionBlock()};
1447 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1448 cir::YieldOp::create(b, loc, res.getRes());
1450 return maybePromoteBoolResult(resOp.getResult(), resTy);
1453 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1455 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1457 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1459 mlir::Value lhs = Visit(e->
getLHS());
1460 mlir::Value rhs = Visit(e->
getRHS());
1462 auto cmpOpKind = cir::CmpOpKind::ne;
1463 lhs = builder.createVecCompare(loc, cmpOpKind, lhs, zeroVec);
1464 rhs = builder.createVecCompare(loc, cmpOpKind, rhs, zeroVec);
1465 return builder.createOr(loc, lhs, rhs);
1469 mlir::Type resTy = cgf.convertType(e->
getType());
1470 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1472 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1474 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1476 auto resOp = cir::TernaryOp::create(
1477 builder, loc, lhsCondV,
1478 [&](mlir::OpBuilder &b, mlir::Location loc) {
1479 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1480 b.getInsertionBlock()};
1482 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1483 cir::YieldOp::create(b, loc, res.getRes());
1486 [&](mlir::OpBuilder &b, mlir::Location loc) {
1487 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1488 b.getInsertionBlock()};
1490 eval.beginEvaluation();
1491 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1492 eval.endEvaluation();
1494 cir::YieldOp::create(b, loc, res);
1497 return maybePromoteBoolResult(resOp.getResult(), resTy);
1500 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1501 return emitLoadOfLValue(e);
1504 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1505 return emitLoadOfLValue(e);
1509 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1510 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1514 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1518 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1520 "ScalarExprEmitter: objc string literal");
1523 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1524 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1527 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1529 "ScalarExprEmitter: objc array literal");
1532 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1534 "ScalarExprEmitter: objc dictionary literal");
1538 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1539 mlir::Value src,
unsigned numElementsDst) {
1540 static constexpr int64_t mask[] = {0, 1, 2, -1};
1541 return builder.createVecShuffle(
1542 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1564 mlir::Type srcTy = src.getType();
1568 return builder.createBitcast(src, dstTy);
1573 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1581 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1585 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1592 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1596 return builder.createIntToPtr(src, dstTy);
1599 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1600 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1601 mlir::Type srcTy = src.getType();
1602 mlir::Type dstTy = cgf.convertType(e->
getType());
1614 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1620 if (numElementsSrc == 3 && numElementsDst != 3) {
1622 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1623 "numElemsDst != 3");
1630 if (numElementsSrc != 3 && numElementsDst == 3) {
1631 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1633 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1635 src = convertVec3AndVec4(builder, loc, src, 3);
1642 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1643 return cgf.emitAtomicExpr(e).getValue();
1647LValue ScalarExprEmitter::emitCompoundAssignLValue(
1649 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1650 mlir::Value &result) {
1661 if (promotionTypeCR.
isNull())
1665 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1667 if (!promotionTypeRHS.
isNull())
1670 opInfo.rhs = Visit(e->
getRHS());
1672 opInfo.fullType = promotionTypeCR;
1673 opInfo.compType = opInfo.fullType;
1674 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1675 opInfo.compType = vecType->getElementType();
1684 if (lhsTy->
getAs<AtomicType>()) {
1685 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1689 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1691 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
1693 if (!promotionTypeLHS.
isNull())
1694 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1696 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1700 result = (this->*func)(opInfo);
1704 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1705 ScalarConversionOpts(cgf.
sanOpts));
1711 if (lhsLV.isBitField())
1722mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1726 cir::CastKind castOpKind;
1728 case CK_FloatingComplexToReal:
1729 castOpKind = cir::CastKind::float_complex_to_real;
1731 case CK_IntegralComplexToReal:
1732 castOpKind = cir::CastKind::int_complex_to_real;
1734 case CK_FloatingComplexToBoolean:
1735 castOpKind = cir::CastKind::float_complex_to_bool;
1737 case CK_IntegralComplexToBoolean:
1738 castOpKind = cir::CastKind::int_complex_to_bool;
1741 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1747mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1748 QualType promotionType) {
1750 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1751 switch (bo->getOpcode()) {
1752#define HANDLE_BINOP(OP) \
1754 return emit##OP(emitBinOps(bo, promotionType));
1763 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1764 switch (uo->getOpcode()) {
1767 return VisitRealImag(uo, promotionType);
1769 return VisitUnaryMinus(uo, promotionType);
1771 return VisitUnaryPlus(uo, promotionType);
1776 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1778 if (!promotionType.
isNull())
1779 return emitPromotedValue(result, promotionType);
1780 return emitUnPromotedValue(result, e->
getType());
1785mlir::Value ScalarExprEmitter::emitCompoundAssign(
1786 const CompoundAssignOperator *e,
1787 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1789 bool ignore = std::exchange(ignoreResultAssign,
false);
1791 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1802 if (!lhs.isVolatile())
1806 return emitLoadOfLValue(lhs, e->
getExprLoc());
1809mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1810 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1825#define COMPOUND_OP(Op) \
1826 case BO_##Op##Assign: \
1827 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1864 llvm_unreachable(
"Not valid compound assignment operators");
1866 llvm_unreachable(
"Unhandled compound assignment operator");
1871 bool ignoreResultAssign) {
1873 "Invalid scalar expression to emit");
1876 .Visit(
const_cast<Expr *
>(e));
1881 if (!promotionType.
isNull())
1896static std::optional<QualType>
1900 return std::nullopt;
1905 return std::nullopt;
1918 const BinOpInfo &op) {
1920 "Expected a unary or binary operator");
1924 if (!op.mayHaveIntegerOverflow())
1928 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1929 return !uo->canOverflow();
1934 std::optional<QualType> optionalLHSTy =
1939 std::optional<QualType> optionalRHSTy =
1949 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1956 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1957 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1962 const BinOpInfo &op,
1963 bool isSubtraction) {
1968 mlir::Value pointer = op.lhs;
1969 Expr *pointerOperand =
expr->getLHS();
1970 mlir::Value
index = op.rhs;
1971 Expr *indexOperand =
expr->getRHS();
1977 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1978 std::swap(pointer,
index);
1979 std::swap(pointerOperand, indexOperand);
1981 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1982 "Need a pointer operand");
1983 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
2018 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
2028 numElements.getType());
2039 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
2044 return cir::PtrStrideOp::create(cgf.
getBuilder(),
2046 pointer.getType(), pointer,
index);
2050 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
2051 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
2061 bool negMul,
bool negAdd) {
2062 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
2063 mlir::Value mulOp0 = mulOp.getLhs();
2064 mlir::Value mulOp1 = mulOp.getRhs();
2072 mlir::Value fmuladd =
2073 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
2074 addend, mulOp.getFenvAttr());
2087 bool isSub =
false) {
2088 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2089 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2090 "Only fadd/fsub can be the root of an fmuladd.");
2099 mlir::Value lhs = op.lhs;
2100 mlir::Value rhs = op.rhs;
2104 bool negLHS =
false;
2105 if (
auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2106 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2107 lhs = lhsNeg.getInput();
2112 bool negRHS =
false;
2113 if (
auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2114 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2115 rhs = rhsNeg.getInput();
2123 if (
auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2124 if (lhsMul.getResult().use_empty() || negLHS) {
2127 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2128 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2131 if (
auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2132 if (rhsMul.getResult().use_empty() || negRHS) {
2135 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2136 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS,
false);
2143mlir::Value ScalarExprEmitter::emitFixedPointIncDec(
const UnaryOperator *e,
2162 if (
type->isSignedFixedPointType()) {
2169 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(
info.loc));
2172 fpbuilder.createIntegerToFixed(
info.rhs,
true, dstSema);
2173 return emitFixedPointBinOp(info);
2176mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2179 mlir::Location loc) {
2182 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2186 result = fpBuilder.createFloatingToFixed(
2190 result = fpBuilder.createFixedToFloating(
2194 llvm::FixedPointSemantics srcFPSema =
2196 llvm::FixedPointSemantics dstFPSema =
2200 result = fpBuilder.createFixedToInteger(
2201 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2204 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2207 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2213mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
2214 const mlir::Location loc = cgf.
getLoc(ops.loc);
2217 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2218 case LangOptions::SOB_Defined:
2219 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2220 return builder.
createMul(loc, ops.lhs, ops.rhs);
2222 case LangOptions::SOB_Undefined:
2223 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2226 case LangOptions::SOB_Trapping:
2234 cgf.
cgm.
errorNYI(
"ScalarExprEmitter::emitMul: matrix types");
2238 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2240 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2242 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2243 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2244 return builder.
createFMul(loc, ops.lhs, ops.rhs);
2247 if (ops.isFixedPointOp())
2248 return emitFixedPointBinOp(ops);
2250 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2253mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2254 const mlir::Location loc = cgf.
getLoc(ops.loc);
2255 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2256 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2257 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2262 cgf.
cgm.
errorNYI(
"ScalarExprEmitter::emitDiv: matrix types");
2266 if (ops.isFixedPointOp())
2267 return emitFixedPointBinOp(ops);
2269 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2272mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2273 const mlir::Location loc = cgf.
getLoc(ops.loc);
2274 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2275 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2276 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2278 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2282mlir::Value ScalarExprEmitter::emitFixedPointBinOp(
const BinOpInfo &ops) {
2287 QualType resultTy = ops.compType;
2288 QualType lhsTy, rhsTy;
2289 if (
const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2290 rhsTy = binOp->getRHS()->getType();
2291 if (
const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2296 lhsTy = cao->getComputationLHSType();
2297 resultTy = cao->getComputationResultType();
2299 lhsTy = binOp->getLHS()->getType();
2301 }
else if (
const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2302 lhsTy = unOp->getSubExpr()->getType();
2303 rhsTy = unOp->getSubExpr()->getType();
2306 mlir::Value lhs = ops.lhs;
2307 mlir::Value rhs = ops.rhs;
2312 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2316 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(ops.loc));
2317 switch (ops.opcode) {
2320 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2324 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2328 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2332 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2336 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2340 result = fpbuilder.createShr(lhs, rhs);
2348 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2349 clangCmpToCIRCmp(ops.opcode));
2353 llvm_unreachable(
"Found unimplemented fixed point binary operation");
2367 "Found unsupported binary operation for fixed point types.");
2373 return fpbuilder.createFixedToFixed(
2374 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2377mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2378 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2379 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2383 const mlir::Location loc = cgf.
getLoc(ops.loc);
2386 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2387 case LangOptions::SOB_Defined:
2388 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2389 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2391 case LangOptions::SOB_Undefined:
2392 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2395 case LangOptions::SOB_Trapping:
2403 cgf.
cgm.
errorNYI(
"ScalarExprEmitter::emitAdd: matrix types");
2408 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2410 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2412 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2413 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2417 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2420 if (ops.isFixedPointOp())
2421 return emitFixedPointBinOp(ops);
2423 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2426mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2427 const mlir::Location loc = cgf.
getLoc(ops.loc);
2429 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2432 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2433 case LangOptions::SOB_Defined: {
2434 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2435 return builder.
createSub(loc, ops.lhs, ops.rhs);
2438 case LangOptions::SOB_Undefined:
2439 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2442 case LangOptions::SOB_Trapping:
2451 cgf.
cgm.
errorNYI(
"ScalarExprEmitter::emitSub: matrix types");
2456 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2458 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2460 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2461 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2463 if (mlir::Value fmuladd =
2466 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2469 if (ops.isFixedPointOp())
2470 return emitFixedPointBinOp(ops);
2472 return builder.
createSub(loc, ops.lhs, ops.rhs);
2477 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2489 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2493mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2495 if (ops.isFixedPointOp())
2496 return emitFixedPointBinOp(ops);
2502 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2506 bool sanitizeUnsignedBase =
2507 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2509 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2510 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2515 else if ((sanitizeBase || sanitizeExponent) &&
2516 mlir::isa<cir::IntType>(ops.lhs.getType()))
2522mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2524 if (ops.isFixedPointOp())
2525 return emitFixedPointBinOp(ops);
2534 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2535 mlir::isa<cir::IntType>(ops.lhs.getType()))
2543mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2544 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2546mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2547 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2549mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2550 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2557mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2559 QualType destTy = ce->
getType();
2561 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2565 ignoreResultAssign =
false;
2568 case clang::CK_Dependent:
2569 llvm_unreachable(
"dependent cast kind in CIR gen!");
2570 case clang::CK_BuiltinFnToFnPtr:
2571 llvm_unreachable(
"builtin functions are handled elsewhere");
2572 case CK_LValueBitCast:
2573 case CK_LValueToRValueBitCast: {
2575 Address sourceAddr = sourceLVal.getAddress();
2581 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2584 case CK_CPointerToObjCPointerCast:
2585 case CK_BlockPointerToObjCPointerCast:
2586 case CK_AnyPointerToBlockPointerCast:
2588 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2593 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2595 "sanitizer support");
2599 "strict vtable pointers");
2625 case CK_AddressSpaceConversion: {
2626 Expr::EvalResult result;
2640 case CK_AtomicToNonAtomic:
2641 case CK_NonAtomicToAtomic:
2642 case CK_UserDefinedConversion:
2643 return Visit(
const_cast<Expr *
>(subExpr));
2647 case CK_IntegralToPointer: {
2649 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2658 : cir::CastKind::integral,
2663 "IntegralToPointer: strict vtable pointers");
2670 case CK_BaseToDerived: {
2672 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2684 case CK_UncheckedDerivedToBase:
2685 case CK_DerivedToBase: {
2696 case CK_ArrayToPointerDecay:
2699 case CK_NullToPointer: {
2709 case CK_NullToMemberPointer: {
2715 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2721 case CK_ReinterpretMemberPointer: {
2722 mlir::Value src = Visit(subExpr);
2726 case CK_BaseToDerivedMemberPointer:
2727 case CK_DerivedToBaseMemberPointer: {
2728 mlir::Value src = Visit(subExpr);
2732 QualType derivedTy =
2733 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2734 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2735 NestedNameSpecifier qualifier = mpType->getQualifier();
2736 assert(qualifier &&
"member pointer without class qualifier");
2737 const Type *qualifierType = qualifier.getAsType();
2738 assert(qualifierType &&
"member pointer qualifier is not a type");
2745 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2748 if (
kind == CK_BaseToDerivedMemberPointer)
2749 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2751 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2754 if (
kind == CK_BaseToDerivedMemberPointer)
2755 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2757 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2761 case CK_LValueToRValue:
2763 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2764 return Visit(
const_cast<Expr *
>(subExpr));
2766 case CK_IntegralCast: {
2767 ScalarConversionOpts opts;
2768 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2769 if (!ice->isPartOfExplicitCast())
2770 opts = ScalarConversionOpts(cgf.
sanOpts);
2772 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2776 case CK_FloatingComplexToReal:
2777 case CK_IntegralComplexToReal:
2778 case CK_FloatingComplexToBoolean:
2779 case CK_IntegralComplexToBoolean: {
2785 case CK_FloatingRealToComplex:
2786 case CK_FloatingComplexCast:
2787 case CK_IntegralRealToComplex:
2788 case CK_IntegralComplexCast:
2789 case CK_IntegralComplexToFloatingComplex:
2790 case CK_FloatingComplexToIntegralComplex:
2791 llvm_unreachable(
"scalar cast to non-scalar value");
2793 case CK_PointerToIntegral: {
2794 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2797 "strict vtable pointers");
2804 case CK_FixedPointCast:
2805 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2808 case CK_FixedPointToBoolean:
2810 "Expected src type to be fixed point type");
2811 assert(destTy->
isBooleanType() &&
"Expected dest type to be boolean type");
2812 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2815 case CK_FixedPointToIntegral:
2817 "Expected src type to be fixed point type");
2818 assert(destTy->
isIntegerType() &&
"Expected dest type to be an integer");
2819 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2822 case CK_IntegralToFixedPoint:
2824 "Expected src type to be an integer");
2826 "Expected dest type to be fixed point type");
2827 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2830 case CK_IntegralToFloating:
2831 case CK_FloatingToIntegral:
2832 case CK_FloatingCast:
2833 case CK_FixedPointToFloating:
2834 case CK_FloatingToFixedPoint: {
2835 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2836 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2840 case CK_IntegralToBoolean:
2841 return emitIntToBoolConversion(Visit(subExpr),
2844 case CK_PointerToBoolean:
2845 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2846 case CK_FloatingToBoolean:
2847 return emitFloatToBoolConversion(Visit(subExpr),
2849 case CK_MemberPointerToBoolean: {
2850 mlir::Value memPtr = Visit(subExpr);
2852 cir::CastKind::member_ptr_to_bool, memPtr,
2856 case CK_VectorSplat: {
2858 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2859 return cir::VecSplatOp::create(builder,
2863 case CK_FunctionToPointerDecay:
2873mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2875 return emitLoadOfLValue(e);
2882mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2887 Expr::EvalResult result;
2889 llvm::APSInt value = result.
Val.
getInt();
2899 return builder.
getBool(value.getBoolValue(), loc);
2902 return emitLoadOfLValue(e);
2905mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2906 const unsigned numInitElements = e->
getNumInits();
2908 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2909 assert((ignore ==
false ||
2911 "init list ignored");
2919 const auto vectorType =
2922 SmallVector<mlir::Value, 16> elements;
2923 for (Expr *init : e->
inits()) {
2924 elements.push_back(Visit(init));
2928 if (numInitElements < vectorType.getSize()) {
2931 std::fill_n(std::back_inserter(elements),
2932 vectorType.getSize() - numInitElements, zeroValue);
2935 return cir::VecCreateOp::create(cgf.
getBuilder(),
2941 if (numInitElements == 0)
2952 "Invalid scalar expression to emit");
2954 .emitScalarConversion(src, srcTy, dstTy, loc);
2962 "Invalid complex -> scalar conversion");
2967 ? cir::CastKind::float_complex_to_bool
2968 : cir::CastKind::int_complex_to_bool;
2973 ? cir::CastKind::float_complex_to_real
2974 : cir::CastKind::int_complex_to_real;
2980mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2987 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2988 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
3002mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
3007 llvm::APSInt value = evalResult.
Val.
getInt();
3013 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
3017mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
3019 mlir::Value result = VisitRealImag(e, promotionTy);
3020 if (result && !promotionTy.
isNull())
3021 result = emitUnPromotedValue(result, e->
getType());
3025mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
3027 mlir::Value result = VisitRealImag(e, promotionTy);
3028 if (result && !promotionTy.
isNull())
3029 result = emitUnPromotedValue(result, e->
getType());
3033mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
3034 QualType promotionTy) {
3037 "Invalid UnaryOp kind for ComplexType Real or Imag");
3059 mlir::Value operand = promotionTy.
isNull()
3061 : cgf.emitPromotedScalarExpr(op, promotionTy);
3067 mlir::Value operand;
3070 operand = cir::LoadOp::create(builder, loc, operand);
3071 }
else if (!promotionTy.
isNull()) {
3081mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
3082 const UnaryExprOrTypeTraitExpr *e) {
3086 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
3087 if (
const VariableArrayType *vat =
3092 bool evaluateExtent =
true;
3093 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3095 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
3098 if (evaluateExtent) {
3109 if (
kind == UETT_CountOf)
3114 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
3115 mlir::Value numElts = vlaSize.
numElts;
3119 if (!eltSize.
isOne()) {
3121 mlir::Value eltSizeValue =
3124 return builder.
createMul(loc, eltSizeValue, numElts,
3131 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
3138 }
else if (e->
getKind() == UETT_VectorElements) {
3140 if (vecTy.getIsScalable()) {
3143 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3150 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getSize()));
3160mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3161 const AbstractConditionalOperator *e) {
3164 ignoreResultAssign =
false;
3167 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3169 Expr *condExpr = e->
getCond();
3177 Expr *live = lhsExpr, *dead = rhsExpr;
3179 std::swap(live, dead);
3185 mlir::Value result = Visit(live);
3192 loc, cir::PoisonAttr::get(builder.getContext(),
3200 QualType condType = condExpr->
getType();
3209 mlir::Value lhsValue = Visit(lhsExpr);
3210 mlir::Value rhsValue = Visit(rhsExpr);
3212 mlir::Type vecTy = convertType(condType);
3213 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
3214 auto testMSB = cir::VecCmpOp::create(
3215 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3217 mlir::Value tmp2 = builder.
createNot(tmp);
3220 mlir::Value rhsTmp = rhsValue;
3221 mlir::Value lhsTmp = lhsValue;
3222 bool wasCast =
false;
3224 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
3230 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
3231 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
3232 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
3241 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
3245 mlir::Value condValue = Visit(condExpr);
3246 mlir::Value lhsValue = Visit(lhsExpr);
3247 mlir::Value rhsValue = Visit(rhsExpr);
3248 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3259 bool lhsIsVoid =
false;
3263 mlir::Value lhs = Visit(lhsExpr);
3269 mlir::Value rhs = Visit(rhsExpr);
3271 assert(!rhs &&
"lhs and rhs types must match");
3279 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
3281 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
3282 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3289 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3291 eval.beginEvaluation();
3292 branch = Visit(
expr);
3293 eval.endEvaluation();
3294 branchCleanups.forceCleanup({&branch});
3298 cir::YieldOp::create(b, loc, branch);
3301 cir::TernaryOp ternary = cir::TernaryOp::create(
3302 builder, loc, condV,
3304 [&](mlir::OpBuilder &b, mlir::Location loc) {
3305 emitBranch(b, loc, lhsExpr);
3308 [&](mlir::OpBuilder &b, mlir::Location loc) {
3309 emitBranch(b, loc, rhsExpr);
3314 for (mlir::Region *region :
3315 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3316 mlir::Block &lastBlock = region->back();
3317 if (lastBlock.empty() ||
3318 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3319 mlir::OpBuilder::InsertionGuard guard(builder);
3320 builder.setInsertionPointToEnd(&lastBlock);
3321 cir::YieldOp::create(builder, loc);
3325 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 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)
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::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
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)
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.
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
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.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
LexicalScope * curLexScope
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
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 emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
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
getQuantity - Get the raw integer representation of this quantity.
bool isOne() const
isOne - Test whether the quantity equals one.
unsigned getValue() const
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
ChildElementIter< false > begin()
size_t getDataElementCount() const
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool 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.
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)
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)
@ Type
The name was classified as a type.
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 fastMathFlags()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool HasSideEffects
Whether the evaluated expression has side effects.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.