20#include "mlir/IR/Location.h"
21#include "mlir/IR/Value.h"
43 bool isDivRemOp()
const {
44 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
45 opcode == BO_RemAssign;
49 bool mayHaveIntegerOverflow()
const {
51 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
52 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
64 bool isFixedPointOp()
const {
67 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
68 QualType lhstype = binOp->getLHS()->getType();
69 QualType rhstype = binOp->getRHS()->getType();
72 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
73 return unop->getSubExpr()->getType()->isFixedPointType();
78class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
81 bool ignoreResultAssign;
85 : cgf(cgf), builder(builder) {}
91 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
95 mlir::Value emitNullValue(
QualType ty, mlir::Location loc) {
99 mlir::Value emitPromotedValue(mlir::Value result,
QualType promotionType) {
103 mlir::Value emitUnPromotedValue(mlir::Value result,
QualType exprType) {
107 mlir::Value emitPromoted(
const Expr *e,
QualType promotionType);
109 mlir::Value maybePromoteBoolResult(mlir::Value value,
110 mlir::Type dstTy)
const {
111 if (mlir::isa<cir::IntType>(dstTy))
113 if (mlir::isa<cir::BoolType>(dstTy))
115 llvm_unreachable(
"Can only promote integer or boolean types");
126 mlir::Value VisitStmt(
Stmt *
s) {
127 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
130 mlir::Value VisitExpr(
Expr *e) {
147 mlir::Value emitLoadOfLValue(
const Expr *e) {
162 return emitLoadOfLValue(e);
167 return builder.create<cir::ConstantOp>(
173 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
174 "expect floating-point type");
175 return builder.create<cir::ConstantOp>(
181 auto init = cir::IntAttr::get(ty, e->
getValue());
196 mlir::Value VisitCastExpr(
CastExpr *e);
197 mlir::Value VisitCallExpr(
const CallExpr *e);
199 mlir::Value VisitStmtExpr(
StmtExpr *e) {
221 return cgf.builder.create<cir::VecExtractOp>(loc, vecValue, indexValue);
224 return emitLoadOfLValue(e);
232 return cgf.builder.create<cir::VecShuffleDynamicOp>(
251 return cgf.builder.create<cir::VecShuffleOp>(
253 vec2, cgf.builder.getArrayAttr(indices));
267 return emitLoadOfLValue(e);
273 return VisitCastExpr(e);
282 mlir::Value emitPointerToBoolConversion(mlir::Value v,
QualType qt) {
288 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
289 cir::BoolType boolTy = builder.
getBoolTy();
290 return builder.create<cir::CastOp>(loc, boolTy,
291 cir::CastKind::float_to_bool, src);
294 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
300 cir::BoolType boolTy = builder.
getBoolTy();
301 return builder.create<cir::CastOp>(loc, boolTy, cir::CastKind::int_to_bool,
307 mlir::Value emitConversionToBool(mlir::Value src,
QualType srcType,
308 mlir::Location loc) {
309 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
312 return emitFloatToBoolConversion(src, loc);
314 if (llvm::isa<MemberPointerType>(srcType)) {
320 return emitIntToBoolConversion(src, loc);
322 assert(::mlir::isa<cir::PointerType>(src.getType()));
323 return emitPointerToBoolConversion(src, srcType);
328 struct ScalarConversionOpts {
329 bool treatBooleanAsSigned;
330 bool emitImplicitIntegerTruncationChecks;
331 bool emitImplicitIntegerSignChangeChecks;
333 ScalarConversionOpts()
334 : treatBooleanAsSigned(
false),
335 emitImplicitIntegerTruncationChecks(
false),
336 emitImplicitIntegerSignChangeChecks(
false) {}
339 : treatBooleanAsSigned(
false),
340 emitImplicitIntegerTruncationChecks(
342 emitImplicitIntegerSignChangeChecks(
350 mlir::Value emitScalarCast(mlir::Value src,
QualType srcType,
352 mlir::Type dstTy, ScalarConversionOpts opts) {
354 "Internal error: matrix types not handled by this function.");
355 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
356 mlir::isa<mlir::IntegerType>(dstTy)) &&
357 "Obsolete code. Don't use mlir::IntegerType with CIR.");
359 mlir::Type fullDstTy = dstTy;
360 if (mlir::isa<cir::VectorType>(srcTy) &&
361 mlir::isa<cir::VectorType>(dstTy)) {
363 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
364 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
367 std::optional<cir::CastKind> castKind;
369 if (mlir::isa<cir::BoolType>(srcTy)) {
370 if (opts.treatBooleanAsSigned)
373 castKind = cir::CastKind::bool_to_int;
374 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
375 castKind = cir::CastKind::bool_to_float;
377 llvm_unreachable(
"Internal error: Cast to unexpected type");
380 castKind = cir::CastKind::integral;
381 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
382 castKind = cir::CastKind::int_to_float;
384 llvm_unreachable(
"Internal error: Cast to unexpected type");
385 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
393 castKind = cir::CastKind::float_to_int;
394 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
398 llvm_unreachable(
"Internal error: Cast to unexpected type");
401 llvm_unreachable(
"Internal error: Cast from unexpected type");
404 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
405 return builder.create<cir::CastOp>(src.getLoc(), fullDstTy, *castKind, src);
413 mlir::Value VisitVAArgExpr(
VAArgExpr *ve) {
418 "variably modified types in varargs");
431 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
435 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
439 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
443 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
446 cir::UnaryOpKind kind,
bool isPre) {
475 if (kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
477 }
else if (
type->isIntegerType()) {
479 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
482 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
483 canPerformLossyDemotionCheck =
true;
484 canPerformLossyDemotionCheck &=
487 canPerformLossyDemotionCheck &=
494 (!canPerformLossyDemotionCheck ||
495 type->isSignedIntegerOrEnumerationType() ||
499 "The following check expects that if we do promotion to different "
500 "underlying canonical type, at least one of the types (either "
501 "base or promoted) will be signed, or the bitwidths will match.");
506 value = emitIncDecConsiderOverflowBehavior(e, value, kind);
508 cir::UnaryOpKind
kind =
509 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
511 value = emitUnaryOp(e, kind, input,
false);
519 }
else if (
type->isFunctionType()) {
522 "Pointer arithmetic on function pointer");
528 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
529 mlir::Value amt = builder.
getSInt32(amount, loc);
533 }
else if (
type->isVectorType()) {
536 }
else if (
type->isRealFloatingType()) {
539 if (
type->isHalfType() &&
545 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
548 assert(kind == cir::UnaryOpKind::Inc ||
549 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
550 value = emitUnaryOp(e, kind, value);
555 }
else if (
type->isFixedPointType()) {
575 return isPre ? value : input;
578 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
580 cir::UnaryOpKind kind) {
581 assert(kind == cir::UnaryOpKind::Inc ||
582 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
583 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
585 return emitUnaryOp(e, kind, inVal,
false);
588 return emitUnaryOp(e, kind, inVal,
true);
591 return emitUnaryOp(e, kind, inVal,
true);
595 llvm_unreachable(
"Unexpected signed overflow behavior kind");
599 if (llvm::isa<MemberPointerType>(e->
getType())) {
611 return emitLoadOfLValue(e);
615 return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
619 return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
623 cir::UnaryOpKind kind) {
624 ignoreResultAssign =
false;
629 if (!promotionType.
isNull())
639 mlir::Value result = emitUnaryOp(e, kind, operand, nsw);
640 if (result && !promotionType.
isNull())
641 return emitUnPromotedValue(result, e->
getType());
645 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind kind,
646 mlir::Value input,
bool nsw =
false) {
647 return builder.create<cir::UnaryOp>(
653 ignoreResultAssign =
false;
655 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
667 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
683 ScalarConversionOpts opts = ScalarConversionOpts()) {
699 if (srcType == dstType) {
700 if (opts.emitImplicitIntegerSignChangeChecks)
702 "implicit integer sign change checks");
709 mlir::Type mlirSrcType = src.getType();
714 return emitConversionToBool(src, srcType, cgf.
getLoc(loc));
721 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
724 "cast via llvm.convert.from.fp16");
731 "cast via llvm.convert.from.fp16");
743 if (mlirSrcType == mlirDstType) {
744 if (opts.emitImplicitIntegerSignChangeChecks)
746 "implicit integer sign change checks");
753 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
755 return builder.
getNullPtr(dstPT, src.getLoc());
758 if (isa<cir::PointerType>(mlirSrcType)) {
760 assert(isa<cir::IntType>(mlirDstType) &&
"not ptr->int?");
770 "Splatted expr doesn't match with vector element type?");
778 "matrix type to matrix type conversion");
782 "Internal error: conversion between matrix type and scalar type");
785 mlir::Value res =
nullptr;
786 mlir::Type resTy = mlirDstType;
788 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
790 if (mlirDstType != resTy) {
800 if (opts.emitImplicitIntegerTruncationChecks)
803 if (opts.emitImplicitIntegerSignChangeChecks)
805 "implicit integer sign change checks");
815 if (!promotionType.
isNull())
816 result.fullType = promotionType;
818 result.fullType = e->
getType();
819 result.compType = result.fullType;
820 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
821 result.compType = vecType->getElementType();
831 mlir::Value emitMul(
const BinOpInfo &ops);
832 mlir::Value emitDiv(
const BinOpInfo &ops);
833 mlir::Value emitRem(
const BinOpInfo &ops);
834 mlir::Value emitAdd(
const BinOpInfo &ops);
835 mlir::Value emitSub(
const BinOpInfo &ops);
836 mlir::Value emitShl(
const BinOpInfo &ops);
837 mlir::Value emitShr(
const BinOpInfo &ops);
838 mlir::Value emitAnd(
const BinOpInfo &ops);
839 mlir::Value emitXor(
const BinOpInfo &ops);
840 mlir::Value emitOr(
const BinOpInfo &ops);
842 LValue emitCompoundAssignLValue(
844 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
845 mlir::Value &result);
848 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
870#define HANDLEBINOP(OP) \
871 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
872 QualType promotionTy = getPromotionType(e->getType()); \
873 auto result = emit##OP(emitBinOps(e, promotionTy)); \
874 if (result && !promotionTy.isNull()) \
875 result = emitUnPromotedValue(result, e->getType()); \
878 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
879 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
900 auto clangCmpToCIRCmp =
904 return cir::CmpOpKind::lt;
906 return cir::CmpOpKind::gt;
908 return cir::CmpOpKind::le;
910 return cir::CmpOpKind::ge;
912 return cir::CmpOpKind::eq;
914 return cir::CmpOpKind::ne;
916 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
920 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
928 BinOpInfo boInfo = emitBinOps(e);
929 mlir::Value lhs = boInfo.lhs;
930 mlir::Value rhs = boInfo.rhs;
940 result = builder.create<cir::VecCmpOp>(
942 boInfo.lhs, boInfo.rhs);
944 }
else if (boInfo.isFixedPointOp()) {
947 result = builder.
getBool(
false, loc);
951 mlir::isa<cir::PointerType>(lhs.getType()) &&
952 mlir::isa<cir::PointerType>(rhs.getType())) {
953 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
956 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
963 BinOpInfo boInfo = emitBinOps(e);
964 result = builder.create<cir::CmpOp>(loc, kind, boInfo.lhs, boInfo.rhs);
972#define VISITCOMP(CODE) \
973 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
983 const bool ignore = std::exchange(ignoreResultAssign,
false);
1032 return emitLoadOfLValue(lhs, e->
getExprLoc());
1038 return Visit(e->
getRHS());
1054 auto resOp = builder.create<cir::TernaryOp>(
1056 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1058 b.getInsertionBlock()};
1063 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1065 b.getInsertionBlock()};
1067 auto res =
b.create<cir::ConstantOp>(loc, builder.
getFalseAttr());
1068 b.create<cir::YieldOp>(loc, res.getRes());
1070 return maybePromoteBoolResult(resOp.getResult(), resTy);
1086 auto resOp = builder.create<cir::TernaryOp>(
1088 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1090 b.getInsertionBlock()};
1092 auto res =
b.create<cir::ConstantOp>(loc, builder.
getTrueAttr());
1093 b.create<cir::YieldOp>(loc, res.getRes());
1096 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1098 b.getInsertionBlock()};
1103 return maybePromoteBoolResult(resOp.getResult(), resTy);
1111LValue ScalarExprEmitter::emitCompoundAssignLValue(
1113 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1114 mlir::Value &result) {
1125 if (promotionTypeCR.
isNull())
1131 if (!promotionTypeRHS.
isNull())
1134 opInfo.rhs = Visit(e->
getRHS());
1136 opInfo.fullType = promotionTypeCR;
1137 opInfo.compType = opInfo.fullType;
1138 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1139 opInfo.compType = vecType->getElementType();
1149 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1153 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1158 if (!promotionTypeLHS.
isNull())
1159 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1161 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1165 result = (this->*func)(opInfo);
1169 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1170 ScalarConversionOpts(cgf.
sanOpts));
1187mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1191 cir::CastKind castOpKind;
1193 case CK_FloatingComplexToReal:
1194 castOpKind = cir::CastKind::float_complex_to_real;
1196 case CK_IntegralComplexToReal:
1197 castOpKind = cir::CastKind::int_complex_to_real;
1199 case CK_FloatingComplexToBoolean:
1200 castOpKind = cir::CastKind::float_complex_to_bool;
1202 case CK_IntegralComplexToBoolean:
1203 castOpKind = cir::CastKind::int_complex_to_bool;
1206 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1212mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1215 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1216 switch (bo->getOpcode()) {
1217#define HANDLE_BINOP(OP) \
1219 return emit##OP(emitBinOps(bo, promotionType));
1228 }
else if (isa<UnaryOperator>(e)) {
1232 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1234 if (!promotionType.
isNull())
1235 return emitPromotedValue(result, promotionType);
1236 return emitUnPromotedValue(result, e->
getType());
1241mlir::Value ScalarExprEmitter::emitCompoundAssign(
1243 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1245 bool ignore = std::exchange(ignoreResultAssign,
false);
1247 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1262 return emitLoadOfLValue(lhs, e->
getExprLoc());
1267 mlir::OpBuilder &builder = cgf.builder;
1269 auto scope = cir::ScopeOp::create(
1272 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1274 builder.getInsertionBlock()};
1275 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1276 if (scopeYieldVal) {
1279 lexScope.forceCleanup();
1280 cir::YieldOp::create(builder, loc, scopeYieldVal);
1281 yieldTy = scopeYieldVal.getType();
1285 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1295#define COMPOUND_OP(Op) \
1296 case BO_##Op##Assign: \
1297 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1334 llvm_unreachable(
"Not valid compound assignment operators");
1336 llvm_unreachable(
"Unhandled compound assignment operator");
1342 "Invalid scalar expression to emit");
1349 if (!promotionType.
isNull())
1358 if (isa<IntegerLiteral>(e) || isa<CXXNullPtrLiteralExpr>(e))
1364static std::optional<QualType>
1368 return std::nullopt;
1373 return std::nullopt;
1386 const BinOpInfo &op) {
1387 assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1388 "Expected a unary or binary operator");
1392 if (!op.mayHaveIntegerOverflow())
1396 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1397 return !uo->canOverflow();
1401 const auto *bo = cast<BinaryOperator>(op.e);
1402 std::optional<QualType> optionalLHSTy =
1407 std::optional<QualType> optionalRHSTy =
1417 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1423 unsigned promotedSize = astContext.
getTypeSize(op.e->getType());
1424 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1425 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1430 const BinOpInfo &op,
1431 bool isSubtraction) {
1436 mlir::Value pointer = op.lhs;
1437 Expr *pointerOperand =
expr->getLHS();
1438 mlir::Value index = op.rhs;
1439 Expr *indexOperand =
expr->getRHS();
1445 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1446 std::swap(pointer, index);
1447 std::swap(pointerOperand, indexOperand);
1449 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1450 "Need a pointer operand");
1451 assert(mlir::isa<cir::IntType>(index.getType()) &&
"Need an integer operand");
1486 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1497 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1502 return cgf.
getBuilder().create<cir::PtrStrideOp>(
1503 cgf.
getLoc(op.e->getExprLoc()), pointer.getType(), pointer, index);
1506mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1507 const mlir::Location loc = cgf.
getLoc(ops.loc);
1508 if (ops.compType->isSignedIntegerOrEnumerationType()) {
1509 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1511 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1512 return builder.createMul(loc, ops.lhs, ops.rhs);
1515 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1516 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1520 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1524 if (ops.fullType->isConstantMatrixType()) {
1529 if (ops.compType->isUnsignedIntegerType() &&
1530 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1532 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1534 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1536 return builder.createFMul(loc, ops.lhs, ops.rhs);
1539 if (ops.isFixedPointOp()) {
1545 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1547 cir::BinOpKind::Mul, ops.lhs, ops.rhs);
1549mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1550 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1552 cir::BinOpKind::Div, ops.lhs, ops.rhs);
1554mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1555 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1557 cir::BinOpKind::Rem, ops.lhs, ops.rhs);
1560mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1561 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1562 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1565 const mlir::Location loc = cgf.
getLoc(ops.loc);
1566 if (ops.compType->isSignedIntegerOrEnumerationType()) {
1567 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1569 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1570 return builder.createAdd(loc, ops.lhs, ops.rhs);
1573 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1574 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1578 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1582 if (ops.fullType->isConstantMatrixType()) {
1588 if (ops.compType->isUnsignedIntegerType() &&
1589 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1591 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1593 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1595 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1598 if (ops.isFixedPointOp()) {
1604 return builder.create<cir::BinOp>(loc, cgf.
convertType(ops.fullType),
1605 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1608mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1609 const mlir::Location loc = cgf.
getLoc(ops.loc);
1611 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1612 if (ops.compType->isSignedIntegerOrEnumerationType()) {
1613 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1615 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1616 return builder.createSub(loc, ops.lhs, ops.rhs);
1620 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1621 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1625 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1630 if (ops.fullType->isConstantMatrixType()) {
1636 if (ops.compType->isUnsignedIntegerType() &&
1637 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1639 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1641 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1643 return builder.createFSub(loc, ops.lhs, ops.rhs);
1646 if (ops.isFixedPointOp()) {
1652 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1654 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1659 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1675mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1677 if (ops.isFixedPointOp()) {
1687 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
1688 ops.compType->hasSignedIntegerRepresentation() &&
1691 bool sanitizeUnsignedBase =
1692 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
1693 ops.compType->hasUnsignedIntegerRepresentation();
1694 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1695 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
1700 else if ((sanitizeBase || sanitizeExponent) &&
1701 mlir::isa<cir::IntType>(ops.lhs.getType()))
1704 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
1707mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
1709 if (ops.isFixedPointOp()) {
1722 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
1723 mlir::isa<cir::IntType>(ops.lhs.getType()))
1728 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
1731mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
1732 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1734 cir::BinOpKind::And, ops.lhs, ops.rhs);
1736mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
1737 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1739 cir::BinOpKind::Xor, ops.lhs, ops.rhs);
1741mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
1742 return builder.create<cir::BinOp>(cgf.
getLoc(ops.loc),
1744 cir::BinOpKind::Or, ops.lhs, ops.rhs);
1751mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
1758 ignoreResultAssign =
false;
1761 case clang::CK_Dependent:
1762 llvm_unreachable(
"dependent cast kind in CIR gen!");
1763 case clang::CK_BuiltinFnToFnPtr:
1764 llvm_unreachable(
"builtin functions are handled elsewhere");
1766 case CK_CPointerToObjCPointerCast:
1767 case CK_BlockPointerToObjCPointerCast:
1768 case CK_AnyPointerToBlockPointerCast:
1770 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
1775 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
1777 "sanitizer support");
1781 "strict vtable pointers");
1808 case CK_AtomicToNonAtomic: {
1814 case CK_NonAtomicToAtomic:
1815 case CK_UserDefinedConversion:
1816 return Visit(
const_cast<Expr *
>(subExpr));
1818 auto v = Visit(
const_cast<Expr *
>(subExpr));
1824 if (t != v.getType())
1830 case CK_ArrayToPointerDecay:
1833 case CK_NullToPointer: {
1843 case CK_LValueToRValue:
1845 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
1846 return Visit(
const_cast<Expr *
>(subExpr));
1848 case CK_IntegralCast: {
1849 ScalarConversionOpts opts;
1850 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
1851 if (!ice->isPartOfExplicitCast())
1852 opts = ScalarConversionOpts(cgf.
sanOpts);
1854 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
1858 case CK_FloatingComplexToReal:
1859 case CK_IntegralComplexToReal:
1860 case CK_FloatingComplexToBoolean:
1861 case CK_IntegralComplexToBoolean: {
1867 case CK_FloatingRealToComplex:
1868 case CK_FloatingComplexCast:
1869 case CK_IntegralRealToComplex:
1870 case CK_IntegralComplexCast:
1871 case CK_IntegralComplexToFloatingComplex:
1872 case CK_FloatingComplexToIntegralComplex:
1873 llvm_unreachable(
"scalar cast to non-scalar value");
1875 case CK_PointerToIntegral: {
1876 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
1879 "strict vtable pointers");
1880 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
1886 case CK_IntegralToFloating:
1887 case CK_FloatingToIntegral:
1888 case CK_FloatingCast:
1889 case CK_FixedPointToFloating:
1890 case CK_FloatingToFixedPoint: {
1891 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
1893 "fixed point casts");
1897 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
1901 case CK_IntegralToBoolean:
1902 return emitIntToBoolConversion(Visit(subExpr),
1905 case CK_PointerToBoolean:
1906 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
1907 case CK_FloatingToBoolean:
1908 return emitFloatToBoolConversion(Visit(subExpr),
1910 case CK_MemberPointerToBoolean: {
1911 mlir::Value memPtr = Visit(subExpr);
1913 cir::CastKind::member_ptr_to_bool, memPtr,
1917 case CK_VectorSplat: {
1919 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
1920 return builder.create<cir::VecSplatOp>(
1924 case CK_FunctionToPointerDecay:
1934mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
1936 return emitLoadOfLValue(e);
1943mlir::Value ScalarExprEmitter::VisitMemberExpr(
MemberExpr *e) {
1953 return emitLoadOfLValue(e);
1956mlir::Value ScalarExprEmitter::VisitInitListExpr(
InitListExpr *e) {
1957 const unsigned numInitElements = e->
getNumInits();
1965 const auto vectorType =
1970 elements.push_back(Visit(init));
1974 if (numInitElements < vectorType.getSize()) {
1977 std::fill_n(std::back_inserter(elements),
1978 vectorType.getSize() - numInitElements, zeroValue);
1981 return cgf.
getBuilder().create<cir::VecCreateOp>(
1986 if (numInitElements == 0)
1997 "Invalid scalar expression to emit");
1999 .emitScalarConversion(src, srcTy, dstTy, loc);
2007 "Invalid complex -> scalar conversion");
2012 ? cir::CastKind::float_complex_to_bool
2013 : cir::CastKind::int_complex_to_bool;
2018 ? cir::CastKind::float_complex_to_real
2019 : cir::CastKind::int_complex_to_real;
2025mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2039 boolVal = builder.createNot(boolVal);
2045mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2060 "VisitUnaryReal calculate and project");
2066mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2081 "VisitUnaryImag calculate and project");
2089mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2094 kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
2097 "sizeof operator for VariableArrayType",
2099 return builder.getConstant(
2101 llvm::APSInt(llvm::APInt(64, 1),
true)));
2103 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2105 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2107 return builder.getConstant(
2109 llvm::APSInt(llvm::APInt(64, 1),
true)));
2112 return builder.getConstant(
2134mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2138 ignoreResultAssign =
false;
2151 Expr *live = lhsExpr, *dead = rhsExpr;
2153 std::swap(live, dead);
2159 mlir::Value result = Visit(live);
2166 "throw expression in conditional operator");
2187 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2191 mlir::Value condValue = Visit(condExpr);
2192 mlir::Value lhsValue = Visit(lhsExpr);
2193 mlir::Value rhsValue = Visit(rhsExpr);
2194 return builder.create<cir::VecTernaryOp>(loc, condValue, lhsValue,
2203 bool lhsIsVoid =
false;
2207 mlir::Value lhs = Visit(lhsExpr);
2213 mlir::Value rhs = Visit(rhsExpr);
2215 assert(!rhs &&
"lhs and rhs types must match");
2225 mlir::Type yieldTy{};
2227 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc,
Expr *
expr) {
2232 eval.beginEvaluation();
2233 mlir::Value branch = Visit(
expr);
2234 eval.endEvaluation();
2237 yieldTy = branch.getType();
2238 b.create<cir::YieldOp>(loc, branch);
2242 insertPoints.push_back(
b.saveInsertionPoint());
2246 mlir::Value result = builder
2247 .create<cir::TernaryOp>(
2250 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2251 emitBranch(
b, loc, lhsExpr);
2254 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2255 emitBranch(
b, loc, rhsExpr);
2259 if (!insertPoints.empty()) {
2265 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2266 mlir::OpBuilder::InsertionGuard guard(builder);
2267 builder.restoreInsertionPoint(toInsert);
2270 if (mlir::isa<cir::VoidType>(yieldTy)) {
2271 builder.create<cir::YieldOp>(loc);
2274 builder.create<cir::YieldOp>(loc, op0);
2284 cir::UnaryOpKind kind,
2287 .emitScalarPrePostIncDec(e, lv, kind, isPre);
ASTImporterLookupTable & LT
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
__device__ __2f16 float __ockl_bool s
cir::ConstantOp getBool(bool state, mlir::Location loc)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
cir::ConstantOp getFalse(mlir::Location loc)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
cir::ConstantOp getTrue(mlir::Location loc)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::BoolAttr getTrueAttr()
cir::BoolAttr getFalseAttr()
cir::BoolType getBoolTy()
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
llvm::APInt getValue() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
const VariableArrayType * getAsVariableArrayType(QualType T) const
const TargetInfo & getTargetInfo() const
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?: operator.
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...
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
mlir::Value getPointer() const
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType)
cir::IntType getSInt64Ty()
cir::ConstantOp getSInt32(int32_t c, mlir::Location loc)
mlir::Value createNeg(mlir::Value value)
An object to manage conditionally-evaluated expressions.
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
An RAII object to record that we're evaluating a statement expression.
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)
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
const clang::LangOptions & getLangOpts() const
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.
mlir::Value loadCXXThis()
Load the value for 'this'.
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).
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
RValue emitAtomicExpr(AtomicExpr *e)
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...
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
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.
void emitCXXThrowExpr(const CXXThrowExpr *e)
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)
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
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.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const clang::CodeGenOptions & getCodeGenOpts() const
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.
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
The null pointer literal (C++11 [lex.nullptr])
An expression "T()" which creates an rvalue of a non-class type T.
Represents the this expression in C++.
A C++ throw-expression (C++ [except.throw]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
static const char * getCastKindName(CastKind CK)
unsigned getValue() const
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
CompoundLiteralExpr - [C99 6.5.2.5].
ConvertVectorExpr - Clang builtin function __builtin_convertvector This AST node provides support for...
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
A reference to a declared variable, function, enum, etc.
ExplicitCastExpr - An explicit cast written in the source code.
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
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, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
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...
ExtVectorType - Extended vector type.
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Represents a C11 generic selection.
Expr * getResultExpr()
Return the result expression of this controlling expression.
Describes an C or C++ initializer list.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
bool isSignedOverflowDefined() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
A pointer to member type per C++ 8.3.3 - Pointers to members.
Represents a pointer to an Objective C object.
Expr * getSelectedExpr() const
ParenExpr - This represents a parenthesized expression, e.g.
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.
ShuffleVectorExpr - clang-specific builtin-in function __builtin_shufflevector.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
CompoundStmt * getSubStmt()
RetTy Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Expr * getReplacement() const
virtual bool useFP16ConversionIntrinsics() const
Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used to convert to and from __fp...
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
bool isExtVectorType() const
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool isMatrixType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
SourceLocation getExprLoc() const
Expr * getSubExpr() const
static bool isIncrementOp(Opcode Op)
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a call to the builtin function __builtin_va_arg.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
QualType getElementType() const
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
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 internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
The JSON file list parser is used to communicate input to InstallAPI.
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool fixedPointType()
static bool vecTernaryOp()
static bool cgFPOptionsRAII()
static bool complexType()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool tryEmitAsConstant()
static bool scalableVectors()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
EvalResult is a struct with detailed info about an evaluated expression.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.