brintos

brintos / llvm-project-archived public Read only

0
0
Text · 98.2 KiB · a8c2061 Raw
2553 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Emit Expr nodes with scalar CIR types as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenFunction.h"14#include "CIRGenValue.h"15 16#include "clang/AST/Expr.h"17#include "clang/AST/StmtVisitor.h"18#include "clang/CIR/Dialect/IR/CIRTypes.h"19#include "clang/CIR/MissingFeatures.h"20 21#include "mlir/IR/Location.h"22#include "mlir/IR/Value.h"23 24#include <cassert>25#include <utility>26 27using namespace clang;28using namespace clang::CIRGen;29 30namespace {31 32struct BinOpInfo {33  mlir::Value lhs;34  mlir::Value rhs;35  SourceRange loc;36  QualType fullType;             // Type of operands and result37  QualType compType;             // Type used for computations. Element type38                                 // for vectors, otherwise same as FullType.39  BinaryOperator::Opcode opcode; // Opcode of BinOp to perform40  FPOptions fpfeatures;41  const Expr *e; // Entire expr, for error unsupported.  May not be binop.42 43  /// Check if the binop computes a division or a remainder.44  bool isDivRemOp() const {45    return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||46           opcode == BO_RemAssign;47  }48 49  /// Check if the binop can result in integer overflow.50  bool mayHaveIntegerOverflow() const {51    // Without constant input, we can't rule out overflow.52    auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();53    auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();54    if (!lhsci || !rhsci)55      return true;56 57    assert(!cir::MissingFeatures::mayHaveIntegerOverflow());58    // TODO(cir): For now we just assume that we might overflow59    return true;60  }61 62  /// Check if at least one operand is a fixed point type. In such cases,63  /// this operation did not follow usual arithmetic conversion and both64  /// operands might not be of the same type.65  bool isFixedPointOp() const {66    // We cannot simply check the result type since comparison operations67    // return an int.68    if (const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {69      QualType lhstype = binOp->getLHS()->getType();70      QualType rhstype = binOp->getRHS()->getType();71      return lhstype->isFixedPointType() || rhstype->isFixedPointType();72    }73    if (const auto *unop = llvm::dyn_cast<UnaryOperator>(e))74      return unop->getSubExpr()->getType()->isFixedPointType();75    return false;76  }77};78 79class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {80  CIRGenFunction &cgf;81  CIRGenBuilderTy &builder;82  // Unlike classic codegen we set this to false or use std::exchange to read83  // the value instead of calling TestAndClearIgnoreResultAssign to make it84  // explicit when the value is used85  bool ignoreResultAssign;86 87public:88  ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,89                    bool ignoreResultAssign = false)90      : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}91 92  //===--------------------------------------------------------------------===//93  //                               Utilities94  //===--------------------------------------------------------------------===//95  mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }96 97  mlir::Value emitComplexToScalarConversion(mlir::Location loc,98                                            mlir::Value value, CastKind kind,99                                            QualType destTy);100 101  mlir::Value emitNullValue(QualType ty, mlir::Location loc) {102    return cgf.cgm.emitNullConstant(ty, loc);103  }104 105  mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {106    return builder.createFloatingCast(result, cgf.convertType(promotionType));107  }108 109  mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {110    return builder.createFloatingCast(result, cgf.convertType(exprType));111  }112 113  mlir::Value emitPromoted(const Expr *e, QualType promotionType);114 115  mlir::Value maybePromoteBoolResult(mlir::Value value,116                                     mlir::Type dstTy) const {117    if (mlir::isa<cir::IntType>(dstTy))118      return builder.createBoolToInt(value, dstTy);119    if (mlir::isa<cir::BoolType>(dstTy))120      return value;121    llvm_unreachable("Can only promote integer or boolean types");122  }123 124  //===--------------------------------------------------------------------===//125  //                            Visitor Methods126  //===--------------------------------------------------------------------===//127 128  mlir::Value Visit(Expr *e) {129    return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);130  }131 132  mlir::Value VisitStmt(Stmt *s) {133    llvm_unreachable("Statement passed to ScalarExprEmitter");134  }135 136  mlir::Value VisitExpr(Expr *e) {137    cgf.getCIRGenModule().errorNYI(138        e->getSourceRange(), "scalar expression kind: ", e->getStmtClassName());139    return {};140  }141 142  mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {143    return Visit(e->getSelectedExpr());144  }145 146  mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }147 148  mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {149    return Visit(ge->getResultExpr());150  }151 152  /// Emits the address of the l-value, then loads and returns the result.153  mlir::Value emitLoadOfLValue(const Expr *e) {154    LValue lv = cgf.emitLValue(e);155    // FIXME: add some akin to EmitLValueAlignmentAssumption(E, V);156    return cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();157  }158 159  mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {160    return cgf.emitCoawaitExpr(*s).getValue();161  }162 163  mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {164    return cgf.emitLoadOfLValue(lv, loc).getValue();165  }166 167  // l-values168  mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {169    if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))170      return cgf.emitScalarConstant(constant, e);171 172    return emitLoadOfLValue(e);173  }174 175  mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) {176    auto func = cast<cir::FuncOp>(cgf.curFn);177    auto blockInfoAttr = cir::BlockAddrInfoAttr::get(178        &cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName());179    return cir::BlockAddressOp::create(builder, cgf.getLoc(e->getSourceRange()),180                                       cgf.convertType(e->getType()),181                                       blockInfoAttr);182  }183 184  mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {185    mlir::Type type = cgf.convertType(e->getType());186    return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),187                                   cir::IntAttr::get(type, e->getValue()));188  }189 190  mlir::Value VisitFloatingLiteral(const FloatingLiteral *e) {191    mlir::Type type = cgf.convertType(e->getType());192    assert(mlir::isa<cir::FPTypeInterface>(type) &&193           "expect floating-point type");194    return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),195                                   cir::FPAttr::get(type, e->getValue()));196  }197 198  mlir::Value VisitCharacterLiteral(const CharacterLiteral *e) {199    mlir::Type ty = cgf.convertType(e->getType());200    auto init = cir::IntAttr::get(ty, e->getValue());201    return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()), init);202  }203 204  mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {205    return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));206  }207 208  mlir::Value VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *e) {209    if (e->getType()->isVoidType())210      return {};211 212    return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));213  }214 215  mlir::Value VisitGNUNullExpr(const GNUNullExpr *e) {216    return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));217  }218 219  mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);220 221  mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {222    if (e->isGLValue())223      return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),224                              e->getExprLoc());225 226    // Otherwise, assume the mapping is the scalar directly.227    return cgf.getOrCreateOpaqueRValueMapping(e).getValue();228  }229 230  mlir::Value VisitCastExpr(CastExpr *e);231  mlir::Value VisitCallExpr(const CallExpr *e);232 233  mlir::Value VisitStmtExpr(StmtExpr *e) {234    CIRGenFunction::StmtExprEvaluation eval(cgf);235    if (e->getType()->isVoidType()) {236      (void)cgf.emitCompoundStmt(*e->getSubStmt());237      return {};238    }239 240    Address retAlloca =241        cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));242    (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);243 244    return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->getType()),245                                e->getExprLoc());246  }247 248  mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {249    ignoreResultAssign = false;250 251    if (e->getBase()->getType()->isVectorType()) {252      assert(!cir::MissingFeatures::scalableVectors());253 254      const mlir::Location loc = cgf.getLoc(e->getSourceRange());255      const mlir::Value vecValue = Visit(e->getBase());256      const mlir::Value indexValue = Visit(e->getIdx());257      return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);258    }259    // Just load the lvalue formed by the subscript expression.260    return emitLoadOfLValue(e);261  }262 263  mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {264    if (e->getNumSubExprs() == 2) {265      // The undocumented form of __builtin_shufflevector.266      mlir::Value inputVec = Visit(e->getExpr(0));267      mlir::Value indexVec = Visit(e->getExpr(1));268      return cir::VecShuffleDynamicOp::create(269          cgf.builder, cgf.getLoc(e->getSourceRange()), inputVec, indexVec);270    }271 272    mlir::Value vec1 = Visit(e->getExpr(0));273    mlir::Value vec2 = Visit(e->getExpr(1));274 275    // The documented form of __builtin_shufflevector, where the indices are276    // a variable number of integer constants. The constants will be stored277    // in an ArrayAttr.278    SmallVector<mlir::Attribute, 8> indices;279    for (unsigned i = 2; i < e->getNumSubExprs(); ++i) {280      indices.push_back(281          cir::IntAttr::get(cgf.builder.getSInt64Ty(),282                            e->getExpr(i)283                                ->EvaluateKnownConstInt(cgf.getContext())284                                .getSExtValue()));285    }286 287    return cir::VecShuffleOp::create(cgf.builder,288                                     cgf.getLoc(e->getSourceRange()),289                                     cgf.convertType(e->getType()), vec1, vec2,290                                     cgf.builder.getArrayAttr(indices));291  }292 293  mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {294    // __builtin_convertvector is an element-wise cast, and is implemented as a295    // regular cast. The back end handles casts of vectors correctly.296    return emitScalarConversion(Visit(e->getSrcExpr()),297                                e->getSrcExpr()->getType(), e->getType(),298                                e->getSourceRange().getBegin());299  }300 301  mlir::Value VisitExtVectorElementExpr(Expr *e) { return emitLoadOfLValue(e); }302 303  mlir::Value VisitMemberExpr(MemberExpr *e);304 305  mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {306    return emitLoadOfLValue(e);307  }308 309  mlir::Value VisitInitListExpr(InitListExpr *e);310 311  mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {312    return VisitCastExpr(e);313  }314 315  mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {316    return cgf.cgm.emitNullConstant(e->getType(),317                                    cgf.getLoc(e->getSourceRange()));318  }319 320  /// Perform a pointer to boolean conversion.321  mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {322    // TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM.323    // We might want to have a separate pass for these types of conversions.324    return cgf.getBuilder().createPtrToBoolCast(v);325  }326 327  mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {328    cir::BoolType boolTy = builder.getBoolTy();329    return cir::CastOp::create(builder, loc, boolTy,330                               cir::CastKind::float_to_bool, src);331  }332 333  mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {334    // Because of the type rules of C, we often end up computing a335    // logical value, then zero extending it to int, then wanting it336    // as a logical value again.337    // TODO: optimize this common case here or leave it for later338    // CIR passes?339    cir::BoolType boolTy = builder.getBoolTy();340    return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,341                               srcVal);342  }343 344  /// Convert the specified expression value to a boolean (!cir.bool) truth345  /// value. This is equivalent to "Val != 0".346  mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,347                                   mlir::Location loc) {348    assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs");349 350    if (srcType->isRealFloatingType())351      return emitFloatToBoolConversion(src, loc);352 353    if (llvm::isa<MemberPointerType>(srcType)) {354      cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion");355      return builder.getFalse(loc);356    }357 358    if (srcType->isIntegerType())359      return emitIntToBoolConversion(src, loc);360 361    assert(::mlir::isa<cir::PointerType>(src.getType()));362    return emitPointerToBoolConversion(src, srcType);363  }364 365  // Emit a conversion from the specified type to the specified destination366  // type, both of which are CIR scalar types.367  struct ScalarConversionOpts {368    bool treatBooleanAsSigned;369    bool emitImplicitIntegerTruncationChecks;370    bool emitImplicitIntegerSignChangeChecks;371 372    ScalarConversionOpts()373        : treatBooleanAsSigned(false),374          emitImplicitIntegerTruncationChecks(false),375          emitImplicitIntegerSignChangeChecks(false) {}376 377    ScalarConversionOpts(clang::SanitizerSet sanOpts)378        : treatBooleanAsSigned(false),379          emitImplicitIntegerTruncationChecks(380              sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),381          emitImplicitIntegerSignChangeChecks(382              sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}383  };384 385  // Conversion from bool, integral, or floating-point to integral or386  // floating-point. Conversions involving other types are handled elsewhere.387  // Conversion to bool is handled elsewhere because that's a comparison against388  // zero, not a simple cast. This handles both individual scalars and vectors.389  mlir::Value emitScalarCast(mlir::Value src, QualType srcType,390                             QualType dstType, mlir::Type srcTy,391                             mlir::Type dstTy, ScalarConversionOpts opts) {392    assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&393           "Internal error: matrix types not handled by this function.");394    assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||395             mlir::isa<mlir::IntegerType>(dstTy)) &&396           "Obsolete code. Don't use mlir::IntegerType with CIR.");397 398    mlir::Type fullDstTy = dstTy;399    if (mlir::isa<cir::VectorType>(srcTy) &&400        mlir::isa<cir::VectorType>(dstTy)) {401      // Use the element types of the vectors to figure out the CastKind.402      srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();403      dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();404    }405 406    std::optional<cir::CastKind> castKind;407 408    if (mlir::isa<cir::BoolType>(srcTy)) {409      if (opts.treatBooleanAsSigned)410        cgf.getCIRGenModule().errorNYI("signed bool");411      if (cgf.getBuilder().isInt(dstTy))412        castKind = cir::CastKind::bool_to_int;413      else if (mlir::isa<cir::FPTypeInterface>(dstTy))414        castKind = cir::CastKind::bool_to_float;415      else416        llvm_unreachable("Internal error: Cast to unexpected type");417    } else if (cgf.getBuilder().isInt(srcTy)) {418      if (cgf.getBuilder().isInt(dstTy))419        castKind = cir::CastKind::integral;420      else if (mlir::isa<cir::FPTypeInterface>(dstTy))421        castKind = cir::CastKind::int_to_float;422      else423        llvm_unreachable("Internal error: Cast to unexpected type");424    } else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {425      if (cgf.getBuilder().isInt(dstTy)) {426        // If we can't recognize overflow as undefined behavior, assume that427        // overflow saturates. This protects against normal optimizations if we428        // are compiling with non-standard FP semantics.429        if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)430          cgf.getCIRGenModule().errorNYI("strict float cast overflow");431        assert(!cir::MissingFeatures::fpConstraints());432        castKind = cir::CastKind::float_to_int;433      } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {434        // TODO: split this to createFPExt/createFPTrunc435        return builder.createFloatingCast(src, fullDstTy);436      } else {437        llvm_unreachable("Internal error: Cast to unexpected type");438      }439    } else {440      llvm_unreachable("Internal error: Cast from unexpected type");441    }442 443    assert(castKind.has_value() && "Internal error: CastKind not set.");444    return cir::CastOp::create(builder, src.getLoc(), fullDstTy, *castKind,445                               src);446  }447 448  mlir::Value449  VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {450    return Visit(e->getReplacement());451  }452 453  mlir::Value VisitVAArgExpr(VAArgExpr *ve) {454    QualType ty = ve->getType();455 456    if (ty->isVariablyModifiedType()) {457      cgf.cgm.errorNYI(ve->getSourceRange(),458                       "variably modified types in varargs");459    }460 461    return cgf.emitVAArg(ve);462  }463 464  mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {465    return Visit(e->getSemanticForm());466  }467 468  mlir::Value VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *e);469  mlir::Value470  VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);471 472  // Unary Operators.473  mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {474    LValue lv = cgf.emitLValue(e->getSubExpr());475    return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec, false);476  }477  mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {478    LValue lv = cgf.emitLValue(e->getSubExpr());479    return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc, false);480  }481  mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {482    LValue lv = cgf.emitLValue(e->getSubExpr());483    return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec, true);484  }485  mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {486    LValue lv = cgf.emitLValue(e->getSubExpr());487    return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc, true);488  }489  mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,490                                      cir::UnaryOpKind kind, bool isPre) {491    if (cgf.getLangOpts().OpenMP)492      cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");493 494    QualType type = e->getSubExpr()->getType();495 496    mlir::Value value;497    mlir::Value input;498 499    if (type->getAs<AtomicType>()) {500      cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");501      // TODO(cir): This is not correct, but it will produce reasonable code502      // until atomic operations are implemented.503      value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();504      input = value;505    } else {506      value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();507      input = value;508    }509 510    // NOTE: When possible, more frequent cases are handled first.511 512    // Special case of integer increment that we have to check first: bool++.513    // Due to promotion rules, we get:514    //   bool++ -> bool = bool + 1515    //          -> bool = (int)bool + 1516    //          -> bool = ((int)bool + 1 != 0)517    // An interesting aspect of this is that increment is always true.518    // Decrement does not have this property.519    if (kind == cir::UnaryOpKind::Inc && type->isBooleanType()) {520      value = builder.getTrue(cgf.getLoc(e->getExprLoc()));521    } else if (type->isIntegerType()) {522      QualType promotedType;523      [[maybe_unused]] bool canPerformLossyDemotionCheck = false;524      if (cgf.getContext().isPromotableIntegerType(type)) {525        promotedType = cgf.getContext().getPromotedIntegerType(type);526        assert(promotedType != type && "Shouldn't promote to the same type.");527        canPerformLossyDemotionCheck = true;528        canPerformLossyDemotionCheck &=529            cgf.getContext().getCanonicalType(type) !=530            cgf.getContext().getCanonicalType(promotedType);531        canPerformLossyDemotionCheck &=532            type->isIntegerType() && promotedType->isIntegerType();533 534        // TODO(cir): Currently, we store bitwidths in CIR types only for535        // integers. This might also be required for other types.536 537        assert(538            (!canPerformLossyDemotionCheck ||539             type->isSignedIntegerOrEnumerationType() ||540             promotedType->isSignedIntegerOrEnumerationType() ||541             mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth() ==542                 mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth()) &&543            "The following check expects that if we do promotion to different "544            "underlying canonical type, at least one of the types (either "545            "base or promoted) will be signed, or the bitwidths will match.");546      }547 548      assert(!cir::MissingFeatures::sanitizers());549      if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) {550        value = emitIncDecConsiderOverflowBehavior(e, value, kind);551      } else {552        cir::UnaryOpKind kind =553            e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;554        // NOTE(CIR): clang calls CreateAdd but folds this to a unary op555        value = emitUnaryOp(e, kind, input, /*nsw=*/false);556      }557    } else if (const PointerType *ptr = type->getAs<PointerType>()) {558      QualType type = ptr->getPointeeType();559      if (cgf.getContext().getAsVariableArrayType(type)) {560        // VLA types don't have constant size.561        cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA");562        return {};563      } else if (type->isFunctionType()) {564        // Arithmetic on function pointers (!) is just +-1.565        cgf.cgm.errorNYI(e->getSourceRange(),566                         "Pointer arithmetic on function pointer");567        return {};568      } else {569        // For everything else, we can just do a simple increment.570        mlir::Location loc = cgf.getLoc(e->getSourceRange());571        CIRGenBuilderTy &builder = cgf.getBuilder();572        int amount = kind == cir::UnaryOpKind::Inc ? 1 : -1;573        mlir::Value amt = builder.getSInt32(amount, loc);574        assert(!cir::MissingFeatures::sanitizers());575        value = builder.createPtrStride(loc, value, amt);576      }577    } else if (type->isVectorType()) {578      cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec vector");579      return {};580    } else if (type->isRealFloatingType()) {581      assert(!cir::MissingFeatures::cgFPOptionsRAII());582 583      if (type->isHalfType() &&584          !cgf.getContext().getLangOpts().NativeHalfType) {585        cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec half");586        return {};587      }588 589      if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {590        // Create the inc/dec operation.591        // NOTE(CIR): clang calls CreateAdd but folds this to a unary op592        assert(kind == cir::UnaryOpKind::Inc ||593               kind == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind");594        value = emitUnaryOp(e, kind, value);595      } else {596        cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");597        return {};598      }599    } else if (type->isFixedPointType()) {600      cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fixed point");601      return {};602    } else {603      assert(type->castAs<ObjCObjectPointerType>());604      cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");605      return {};606    }607 608    CIRGenFunction::SourceLocRAIIObject sourceloc{609        cgf, cgf.getLoc(e->getSourceRange())};610 611    // Store the updated result through the lvalue612    if (lv.isBitField())613      return cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);614    else615      cgf.emitStoreThroughLValue(RValue::get(value), lv);616 617    // If this is a postinc, return the value read from memory, otherwise use618    // the updated value.619    return isPre ? value : input;620  }621 622  mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,623                                                 mlir::Value inVal,624                                                 cir::UnaryOpKind kind) {625    assert(kind == cir::UnaryOpKind::Inc ||626           kind == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind");627    switch (cgf.getLangOpts().getSignedOverflowBehavior()) {628    case LangOptions::SOB_Defined:629      return emitUnaryOp(e, kind, inVal, /*nsw=*/false);630    case LangOptions::SOB_Undefined:631      assert(!cir::MissingFeatures::sanitizers());632      return emitUnaryOp(e, kind, inVal, /*nsw=*/true);633    case LangOptions::SOB_Trapping:634      if (!e->canOverflow())635        return emitUnaryOp(e, kind, inVal, /*nsw=*/true);636      cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");637      return {};638    }639    llvm_unreachable("Unexpected signed overflow behavior kind");640  }641 642  mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {643    if (llvm::isa<MemberPointerType>(e->getType())) {644      cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer");645      return builder.getNullPtr(cgf.convertType(e->getType()),646                                cgf.getLoc(e->getExprLoc()));647    }648 649    return cgf.emitLValue(e->getSubExpr()).getPointer();650  }651 652  mlir::Value VisitUnaryDeref(const UnaryOperator *e) {653    if (e->getType()->isVoidType())654      return Visit(e->getSubExpr()); // the actual value should be unused655    return emitLoadOfLValue(e);656  }657 658  mlir::Value VisitUnaryPlus(const UnaryOperator *e) {659    QualType promotionType = getPromotionType(e->getSubExpr()->getType());660    mlir::Value result =661        emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);662    if (result && !promotionType.isNull())663      return emitUnPromotedValue(result, e->getType());664    return result;665  }666 667  mlir::Value VisitUnaryMinus(const UnaryOperator *e) {668    QualType promotionType = getPromotionType(e->getSubExpr()->getType());669    mlir::Value result =670        emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);671    if (result && !promotionType.isNull())672      return emitUnPromotedValue(result, e->getType());673    return result;674  }675 676  mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e,677                                   cir::UnaryOpKind kind,678                                   QualType promotionType) {679    ignoreResultAssign = false;680    mlir::Value operand;681    if (!promotionType.isNull())682      operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);683    else684      operand = Visit(e->getSubExpr());685 686    bool nsw =687        kind == cir::UnaryOpKind::Minus && e->getType()->isSignedIntegerType();688 689    // NOTE: LLVM codegen will lower this directly to either a FNeg690    // or a Sub instruction.  In CIR this will be handled later in LowerToLLVM.691    return emitUnaryOp(e, kind, operand, nsw);692  }693 694  mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind,695                          mlir::Value input, bool nsw = false) {696    return cir::UnaryOp::create(builder,697                                cgf.getLoc(e->getSourceRange().getBegin()),698                                input.getType(), kind, input, nsw);699  }700 701  mlir::Value VisitUnaryNot(const UnaryOperator *e) {702    ignoreResultAssign = false;703    mlir::Value op = Visit(e->getSubExpr());704    return emitUnaryOp(e, cir::UnaryOpKind::Not, op);705  }706 707  mlir::Value VisitUnaryLNot(const UnaryOperator *e);708 709  mlir::Value VisitUnaryReal(const UnaryOperator *e);710  mlir::Value VisitUnaryImag(const UnaryOperator *e);711  mlir::Value VisitRealImag(const UnaryOperator *e,712                            QualType promotionType = QualType());713 714  mlir::Value VisitUnaryExtension(const UnaryOperator *e) {715    return Visit(e->getSubExpr());716  }717 718  mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {719    CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);720    return Visit(dae->getExpr());721  }722  mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {723    CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);724    return Visit(die->getExpr());725  }726 727  mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }728 729  mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);730  mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {731    return cgf.emitCXXNewExpr(e);732  }733  mlir::Value VisitCXXDeleteExpr(const CXXDeleteExpr *e) {734    cgf.emitCXXDeleteExpr(e);735    return {};736  }737 738  mlir::Value VisitCXXThrowExpr(const CXXThrowExpr *e) {739    cgf.emitCXXThrowExpr(e);740    return {};741  }742 743  /// Emit a conversion from the specified type to the specified destination744  /// type, both of which are CIR scalar types.745  /// TODO: do we need ScalarConversionOpts here? Should be done in another746  /// pass.747  mlir::Value748  emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,749                       SourceLocation loc,750                       ScalarConversionOpts opts = ScalarConversionOpts()) {751    // All conversions involving fixed point types should be handled by the752    // emitFixedPoint family functions. This is done to prevent bloating up753    // this function more, and although fixed point numbers are represented by754    // integers, we do not want to follow any logic that assumes they should be755    // treated as integers.756    // TODO(leonardchan): When necessary, add another if statement checking for757    // conversions to fixed point types from other types.758    // conversions to fixed point types from other types.759    if (srcType->isFixedPointType() || dstType->isFixedPointType()) {760      cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions");761      return {};762    }763 764    srcType = srcType.getCanonicalType();765    dstType = dstType.getCanonicalType();766    if (srcType == dstType) {767      if (opts.emitImplicitIntegerSignChangeChecks)768        cgf.getCIRGenModule().errorNYI(loc,769                                       "implicit integer sign change checks");770      return src;771    }772 773    if (dstType->isVoidType())774      return {};775 776    mlir::Type mlirSrcType = src.getType();777 778    // Handle conversions to bool first, they are special: comparisons against779    // 0.780    if (dstType->isBooleanType())781      return emitConversionToBool(src, srcType, cgf.getLoc(loc));782 783    mlir::Type mlirDstType = cgf.convertType(dstType);784 785    if (srcType->isHalfType() &&786        !cgf.getContext().getLangOpts().NativeHalfType) {787      // Cast to FP using the intrinsic if the half type itself isn't supported.788      if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {789        if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())790          cgf.getCIRGenModule().errorNYI(loc,791                                         "cast via llvm.convert.from.fp16");792      } else {793        // Cast to other types through float, using either the intrinsic or794        // FPExt, depending on whether the half type itself is supported (as795        // opposed to operations on half, available with NativeHalfType).796        if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())797          cgf.getCIRGenModule().errorNYI(loc,798                                         "cast via llvm.convert.from.fp16");799        // FIXME(cir): For now lets pretend we shouldn't use the conversion800        // intrinsics and insert a cast here unconditionally.801        src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,802                                 cgf.floatTy);803        srcType = cgf.getContext().FloatTy;804        mlirSrcType = cgf.floatTy;805      }806    }807 808    // TODO(cir): LLVM codegen ignore conversions like int -> uint,809    // is there anything to be done for CIR here?810    if (mlirSrcType == mlirDstType) {811      if (opts.emitImplicitIntegerSignChangeChecks)812        cgf.getCIRGenModule().errorNYI(loc,813                                       "implicit integer sign change checks");814      return src;815    }816 817    // Handle pointer conversions next: pointers can only be converted to/from818    // other pointers and integers. Check for pointer types in terms of LLVM, as819    // some native types (like Obj-C id) may map to a pointer type.820    if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {821      cgf.getCIRGenModule().errorNYI(loc, "pointer casts");822      return builder.getNullPtr(dstPT, src.getLoc());823    }824 825    if (isa<cir::PointerType>(mlirSrcType)) {826      // Must be an ptr to int cast.827      assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");828      return builder.createPtrToInt(src, mlirDstType);829    }830 831    // A scalar can be splatted to an extended vector of the same element type832    if (dstType->isExtVectorType() && !srcType->isVectorType()) {833      // Sema should add casts to make sure that the source expression's type834      // is the same as the vector's element type (sans qualifiers)835      assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==836                 srcType.getTypePtr() &&837             "Splatted expr doesn't match with vector element type?");838 839      cgf.getCIRGenModule().errorNYI(loc, "vector splatting");840      return {};841    }842 843    if (srcType->isMatrixType() && dstType->isMatrixType()) {844      cgf.getCIRGenModule().errorNYI(loc,845                                     "matrix type to matrix type conversion");846      return {};847    }848    assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&849           "Internal error: conversion between matrix type and scalar type");850 851    // Finally, we have the arithmetic types or vectors of arithmetic types.852    mlir::Value res = nullptr;853    mlir::Type resTy = mlirDstType;854 855    res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);856 857    if (mlirDstType != resTy) {858      if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {859        cgf.getCIRGenModule().errorNYI(loc, "cast via llvm.convert.to.fp16");860      }861      // FIXME(cir): For now we never use FP16 conversion intrinsics even if862      // required by the target. Change that once this is implemented863      res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,864                               resTy);865    }866 867    if (opts.emitImplicitIntegerTruncationChecks)868      cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");869 870    if (opts.emitImplicitIntegerSignChangeChecks)871      cgf.getCIRGenModule().errorNYI(loc,872                                     "implicit integer sign change checks");873 874    return res;875  }876 877  BinOpInfo emitBinOps(const BinaryOperator *e,878                       QualType promotionType = QualType()) {879    ignoreResultAssign = false;880    BinOpInfo result;881    result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);882    result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);883    if (!promotionType.isNull())884      result.fullType = promotionType;885    else886      result.fullType = e->getType();887    result.compType = result.fullType;888    if (const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {889      result.compType = vecType->getElementType();890    }891    result.opcode = e->getOpcode();892    result.loc = e->getSourceRange();893    // TODO(cir): Result.FPFeatures894    assert(!cir::MissingFeatures::cgFPOptionsRAII());895    result.e = e;896    return result;897  }898 899  mlir::Value emitMul(const BinOpInfo &ops);900  mlir::Value emitDiv(const BinOpInfo &ops);901  mlir::Value emitRem(const BinOpInfo &ops);902  mlir::Value emitAdd(const BinOpInfo &ops);903  mlir::Value emitSub(const BinOpInfo &ops);904  mlir::Value emitShl(const BinOpInfo &ops);905  mlir::Value emitShr(const BinOpInfo &ops);906  mlir::Value emitAnd(const BinOpInfo &ops);907  mlir::Value emitXor(const BinOpInfo &ops);908  mlir::Value emitOr(const BinOpInfo &ops);909 910  LValue emitCompoundAssignLValue(911      const CompoundAssignOperator *e,912      mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),913      mlir::Value &result);914  mlir::Value915  emitCompoundAssign(const CompoundAssignOperator *e,916                     mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));917 918  // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM919  // codegen.920  QualType getPromotionType(QualType ty) {921    const clang::ASTContext &ctx = cgf.getContext();922    if (auto *complexTy = ty->getAs<ComplexType>()) {923      QualType elementTy = complexTy->getElementType();924      if (elementTy.UseExcessPrecision(ctx))925        return ctx.getComplexType(ctx.FloatTy);926    }927 928    if (ty.UseExcessPrecision(cgf.getContext())) {929      if (auto *vt = ty->getAs<VectorType>()) {930        unsigned numElements = vt->getNumElements();931        return ctx.getVectorType(ctx.FloatTy, numElements, vt->getVectorKind());932      }933      return cgf.getContext().FloatTy;934    }935 936    return QualType();937  }938 939// Binary operators and binary compound assignment operators.940#define HANDLEBINOP(OP)                                                        \941  mlir::Value VisitBin##OP(const BinaryOperator *e) {                          \942    QualType promotionTy = getPromotionType(e->getType());                     \943    auto result = emit##OP(emitBinOps(e, promotionTy));                        \944    if (result && !promotionTy.isNull())                                       \945      result = emitUnPromotedValue(result, e->getType());                      \946    return result;                                                             \947  }                                                                            \948  mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) {          \949    return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP);                \950  }951 952  HANDLEBINOP(Mul)953  HANDLEBINOP(Div)954  HANDLEBINOP(Rem)955  HANDLEBINOP(Add)956  HANDLEBINOP(Sub)957  HANDLEBINOP(Shl)958  HANDLEBINOP(Shr)959  HANDLEBINOP(And)960  HANDLEBINOP(Xor)961  HANDLEBINOP(Or)962#undef HANDLEBINOP963 964  mlir::Value emitCmp(const BinaryOperator *e) {965    ignoreResultAssign = false;966    const mlir::Location loc = cgf.getLoc(e->getExprLoc());967    mlir::Value result;968    QualType lhsTy = e->getLHS()->getType();969    QualType rhsTy = e->getRHS()->getType();970 971    auto clangCmpToCIRCmp =972        [](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {973      switch (clangCmp) {974      case BO_LT:975        return cir::CmpOpKind::lt;976      case BO_GT:977        return cir::CmpOpKind::gt;978      case BO_LE:979        return cir::CmpOpKind::le;980      case BO_GE:981        return cir::CmpOpKind::ge;982      case BO_EQ:983        return cir::CmpOpKind::eq;984      case BO_NE:985        return cir::CmpOpKind::ne;986      default:987        llvm_unreachable("unsupported comparison kind for cir.cmp");988      }989    };990 991    cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());992    if (lhsTy->getAs<MemberPointerType>()) {993      assert(!cir::MissingFeatures::dataMemberType());994      assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);995      mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());996      mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());997      result = builder.createCompare(loc, kind, lhs, rhs);998    } else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {999      BinOpInfo boInfo = emitBinOps(e);1000      mlir::Value lhs = boInfo.lhs;1001      mlir::Value rhs = boInfo.rhs;1002 1003      if (lhsTy->isVectorType()) {1004        if (!e->getType()->isVectorType()) {1005          // If AltiVec, the comparison results in a numeric type, so we use1006          // intrinsics comparing vectors and giving 0 or 1 as a result1007          cgf.cgm.errorNYI(loc, "AltiVec comparison");1008        } else {1009          // Other kinds of vectors. Element-wise comparison returning1010          // a vector.1011          result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),1012                                         cgf.convertType(boInfo.fullType), kind,1013                                         boInfo.lhs, boInfo.rhs);1014        }1015      } else if (boInfo.isFixedPointOp()) {1016        assert(!cir::MissingFeatures::fixedPointType());1017        cgf.cgm.errorNYI(loc, "fixed point comparisons");1018        result = builder.getBool(false, loc);1019      } else {1020        // integers and pointers1021        if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&1022            mlir::isa<cir::PointerType>(lhs.getType()) &&1023            mlir::isa<cir::PointerType>(rhs.getType())) {1024          cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");1025        }1026 1027        cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());1028        result = builder.createCompare(loc, kind, lhs, rhs);1029      }1030    } else {1031      // Complex Comparison: can only be an equality comparison.1032      assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);1033 1034      BinOpInfo boInfo = emitBinOps(e);1035      result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);1036    }1037 1038    return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),1039                                e->getExprLoc());1040  }1041 1042// Comparisons.1043#define VISITCOMP(CODE)                                                        \1044  mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }1045  VISITCOMP(LT)1046  VISITCOMP(GT)1047  VISITCOMP(LE)1048  VISITCOMP(GE)1049  VISITCOMP(EQ)1050  VISITCOMP(NE)1051#undef VISITCOMP1052 1053  mlir::Value VisitBinAssign(const BinaryOperator *e) {1054    const bool ignore = std::exchange(ignoreResultAssign, false);1055 1056    mlir::Value rhs;1057    LValue lhs;1058 1059    switch (e->getLHS()->getType().getObjCLifetime()) {1060    case Qualifiers::OCL_Strong:1061    case Qualifiers::OCL_Autoreleasing:1062    case Qualifiers::OCL_ExplicitNone:1063    case Qualifiers::OCL_Weak:1064      assert(!cir::MissingFeatures::objCLifetime());1065      break;1066    case Qualifiers::OCL_None:1067      // __block variables need to have the rhs evaluated first, plus this1068      // should improve codegen just a little.1069      rhs = Visit(e->getRHS());1070      assert(!cir::MissingFeatures::sanitizers());1071      // TODO(cir): This needs to be emitCheckedLValue() once we support1072      // sanitizers1073      lhs = cgf.emitLValue(e->getLHS());1074 1075      // Store the value into the LHS. Bit-fields are handled specially because1076      // the result is altered by the store, i.e., [C99 6.5.16p1]1077      // 'An assignment expression has the value of the left operand after the1078      // assignment...'.1079      if (lhs.isBitField()) {1080        rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);1081      } else {1082        cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());1083        CIRGenFunction::SourceLocRAIIObject loc{1084            cgf, cgf.getLoc(e->getSourceRange())};1085        cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);1086      }1087    }1088 1089    // If the result is clearly ignored, return now.1090    if (ignore)1091      return nullptr;1092 1093    // The result of an assignment in C is the assigned r-value.1094    if (!cgf.getLangOpts().CPlusPlus)1095      return rhs;1096 1097    // If the lvalue is non-volatile, return the computed value of the1098    // assignment.1099    if (!lhs.isVolatile())1100      return rhs;1101 1102    // Otherwise, reload the value.1103    return emitLoadOfLValue(lhs, e->getExprLoc());1104  }1105 1106  mlir::Value VisitBinComma(const BinaryOperator *e) {1107    cgf.emitIgnoredExpr(e->getLHS());1108    // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.1109    return Visit(e->getRHS());1110  }1111 1112  mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {1113    if (e->getType()->isVectorType()) {1114      mlir::Location loc = cgf.getLoc(e->getExprLoc());1115      auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));1116      mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);1117      SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);1118      auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);1119 1120      mlir::Value lhs = Visit(e->getLHS());1121      mlir::Value rhs = Visit(e->getRHS());1122 1123      auto cmpOpKind = cir::CmpOpKind::ne;1124      lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);1125      rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);1126      mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);1127      return builder.createIntCast(vecOr, vecTy);1128    }1129 1130    assert(!cir::MissingFeatures::instrumentation());1131    mlir::Type resTy = cgf.convertType(e->getType());1132    mlir::Location loc = cgf.getLoc(e->getExprLoc());1133 1134    CIRGenFunction::ConditionalEvaluation eval(cgf);1135 1136    mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());1137    auto resOp = cir::TernaryOp::create(1138        builder, loc, lhsCondV, /*trueBuilder=*/1139        [&](mlir::OpBuilder &b, mlir::Location loc) {1140          CIRGenFunction::LexicalScope lexScope{cgf, loc,1141                                                b.getInsertionBlock()};1142          cgf.curLexScope->setAsTernary();1143          mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());1144          lexScope.forceCleanup();1145          cir::YieldOp::create(b, loc, res);1146        },1147        /*falseBuilder*/1148        [&](mlir::OpBuilder &b, mlir::Location loc) {1149          CIRGenFunction::LexicalScope lexScope{cgf, loc,1150                                                b.getInsertionBlock()};1151          cgf.curLexScope->setAsTernary();1152          auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());1153          cir::YieldOp::create(b, loc, res.getRes());1154        });1155    return maybePromoteBoolResult(resOp.getResult(), resTy);1156  }1157 1158  mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {1159    if (e->getType()->isVectorType()) {1160      mlir::Location loc = cgf.getLoc(e->getExprLoc());1161      auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));1162      mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);1163      SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);1164      auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);1165 1166      mlir::Value lhs = Visit(e->getLHS());1167      mlir::Value rhs = Visit(e->getRHS());1168 1169      auto cmpOpKind = cir::CmpOpKind::ne;1170      lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);1171      rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);1172      mlir::Value vecOr = builder.createOr(loc, lhs, rhs);1173      return builder.createIntCast(vecOr, vecTy);1174    }1175 1176    assert(!cir::MissingFeatures::instrumentation());1177    mlir::Type resTy = cgf.convertType(e->getType());1178    mlir::Location loc = cgf.getLoc(e->getExprLoc());1179 1180    CIRGenFunction::ConditionalEvaluation eval(cgf);1181 1182    mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());1183    auto resOp = cir::TernaryOp::create(1184        builder, loc, lhsCondV, /*trueBuilder=*/1185        [&](mlir::OpBuilder &b, mlir::Location loc) {1186          CIRGenFunction::LexicalScope lexScope{cgf, loc,1187                                                b.getInsertionBlock()};1188          cgf.curLexScope->setAsTernary();1189          auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());1190          cir::YieldOp::create(b, loc, res.getRes());1191        },1192        /*falseBuilder*/1193        [&](mlir::OpBuilder &b, mlir::Location loc) {1194          CIRGenFunction::LexicalScope lexScope{cgf, loc,1195                                                b.getInsertionBlock()};1196          cgf.curLexScope->setAsTernary();1197          mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());1198          lexScope.forceCleanup();1199          cir::YieldOp::create(b, loc, res);1200        });1201 1202    return maybePromoteBoolResult(resOp.getResult(), resTy);1203  }1204 1205  mlir::Value VisitAtomicExpr(AtomicExpr *e) {1206    return cgf.emitAtomicExpr(e).getValue();1207  }1208};1209 1210LValue ScalarExprEmitter::emitCompoundAssignLValue(1211    const CompoundAssignOperator *e,1212    mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),1213    mlir::Value &result) {1214  if (e->getComputationResultType()->isAnyComplexType())1215    return cgf.emitScalarCompoundAssignWithComplex(e, result);1216 1217  QualType lhsTy = e->getLHS()->getType();1218  BinOpInfo opInfo;1219 1220  // Emit the RHS first.  __block variables need to have the rhs evaluated1221  // first, plus this should improve codegen a little.1222 1223  QualType promotionTypeCR = getPromotionType(e->getComputationResultType());1224  if (promotionTypeCR.isNull())1225    promotionTypeCR = e->getComputationResultType();1226 1227  QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());1228  QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());1229 1230  if (!promotionTypeRHS.isNull())1231    opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);1232  else1233    opInfo.rhs = Visit(e->getRHS());1234 1235  opInfo.fullType = promotionTypeCR;1236  opInfo.compType = opInfo.fullType;1237  if (const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))1238    opInfo.compType = vecType->getElementType();1239  opInfo.opcode = e->getOpcode();1240  opInfo.fpfeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());1241  opInfo.e = e;1242  opInfo.loc = e->getSourceRange();1243 1244  // Load/convert the LHS1245  LValue lhsLV = cgf.emitLValue(e->getLHS());1246 1247  if (lhsTy->getAs<AtomicType>()) {1248    cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");1249    return LValue();1250  }1251 1252  opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());1253 1254  CIRGenFunction::SourceLocRAIIObject sourceloc{1255      cgf, cgf.getLoc(e->getSourceRange())};1256  SourceLocation loc = e->getExprLoc();1257  if (!promotionTypeLHS.isNull())1258    opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);1259  else1260    opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,1261                                      e->getComputationLHSType(), loc);1262 1263  // Expand the binary operator.1264  result = (this->*func)(opInfo);1265 1266  // Convert the result back to the LHS type,1267  // potentially with Implicit Conversion sanitizer check.1268  result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,1269                                ScalarConversionOpts(cgf.sanOpts));1270 1271  // Store the result value into the LHS lvalue. Bit-fields are handled1272  // specially because the result is altered by the store, i.e., [C99 6.5.16p1]1273  // 'An assignment expression has the value of the left operand after the1274  // assignment...'.1275  if (lhsLV.isBitField())1276    cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);1277  else1278    cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);1279 1280  if (cgf.getLangOpts().OpenMP)1281    cgf.cgm.errorNYI(e->getSourceRange(), "openmp");1282 1283  return lhsLV;1284}1285 1286mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,1287                                                             mlir::Value value,1288                                                             CastKind kind,1289                                                             QualType destTy) {1290  cir::CastKind castOpKind;1291  switch (kind) {1292  case CK_FloatingComplexToReal:1293    castOpKind = cir::CastKind::float_complex_to_real;1294    break;1295  case CK_IntegralComplexToReal:1296    castOpKind = cir::CastKind::int_complex_to_real;1297    break;1298  case CK_FloatingComplexToBoolean:1299    castOpKind = cir::CastKind::float_complex_to_bool;1300    break;1301  case CK_IntegralComplexToBoolean:1302    castOpKind = cir::CastKind::int_complex_to_bool;1303    break;1304  default:1305    llvm_unreachable("invalid complex-to-scalar cast kind");1306  }1307 1308  return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));1309}1310 1311mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,1312                                            QualType promotionType) {1313  e = e->IgnoreParens();1314  if (const auto *bo = dyn_cast<BinaryOperator>(e)) {1315    switch (bo->getOpcode()) {1316#define HANDLE_BINOP(OP)                                                       \1317  case BO_##OP:                                                                \1318    return emit##OP(emitBinOps(bo, promotionType));1319      HANDLE_BINOP(Add)1320      HANDLE_BINOP(Sub)1321      HANDLE_BINOP(Mul)1322      HANDLE_BINOP(Div)1323#undef HANDLE_BINOP1324    default:1325      break;1326    }1327  } else if (const auto *uo = dyn_cast<UnaryOperator>(e)) {1328    switch (uo->getOpcode()) {1329    case UO_Imag:1330    case UO_Real:1331      return VisitRealImag(uo, promotionType);1332    case UO_Minus:1333      return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);1334    case UO_Plus:1335      return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);1336    default:1337      break;1338    }1339  }1340  mlir::Value result = Visit(const_cast<Expr *>(e));1341  if (result) {1342    if (!promotionType.isNull())1343      return emitPromotedValue(result, promotionType);1344    return emitUnPromotedValue(result, e->getType());1345  }1346  return result;1347}1348 1349mlir::Value ScalarExprEmitter::emitCompoundAssign(1350    const CompoundAssignOperator *e,1351    mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {1352 1353  bool ignore = std::exchange(ignoreResultAssign, false);1354  mlir::Value rhs;1355  LValue lhs = emitCompoundAssignLValue(e, func, rhs);1356 1357  // If the result is clearly ignored, return now.1358  if (ignore)1359    return {};1360 1361  // The result of an assignment in C is the assigned r-value.1362  if (!cgf.getLangOpts().CPlusPlus)1363    return rhs;1364 1365  // If the lvalue is non-volatile, return the computed value of the assignment.1366  if (!lhs.isVolatile())1367    return rhs;1368 1369  // Otherwise, reload the value.1370  return emitLoadOfLValue(lhs, e->getExprLoc());1371}1372 1373mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {1374  mlir::Location scopeLoc = cgf.getLoc(e->getSourceRange());1375  mlir::OpBuilder &builder = cgf.builder;1376 1377  auto scope = cir::ScopeOp::create(1378      builder, scopeLoc,1379      /*scopeBuilder=*/1380      [&](mlir::OpBuilder &b, mlir::Type &yieldTy, mlir::Location loc) {1381        CIRGenFunction::LexicalScope lexScope{cgf, loc,1382                                              builder.getInsertionBlock()};1383        mlir::Value scopeYieldVal = Visit(e->getSubExpr());1384        if (scopeYieldVal) {1385          // Defend against dominance problems caused by jumps out of expression1386          // evaluation through the shared cleanup block.1387          lexScope.forceCleanup();1388          cir::YieldOp::create(builder, loc, scopeYieldVal);1389          yieldTy = scopeYieldVal.getType();1390        }1391      });1392 1393  return scope.getNumResults() > 0 ? scope->getResult(0) : nullptr;1394}1395 1396} // namespace1397 1398LValue1399CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {1400  ScalarExprEmitter emitter(*this, builder);1401  mlir::Value result;1402  switch (e->getOpcode()) {1403#define COMPOUND_OP(Op)                                                        \1404  case BO_##Op##Assign:                                                        \1405    return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op,   \1406                                            result)1407    COMPOUND_OP(Mul);1408    COMPOUND_OP(Div);1409    COMPOUND_OP(Rem);1410    COMPOUND_OP(Add);1411    COMPOUND_OP(Sub);1412    COMPOUND_OP(Shl);1413    COMPOUND_OP(Shr);1414    COMPOUND_OP(And);1415    COMPOUND_OP(Xor);1416    COMPOUND_OP(Or);1417#undef COMPOUND_OP1418 1419  case BO_PtrMemD:1420  case BO_PtrMemI:1421  case BO_Mul:1422  case BO_Div:1423  case BO_Rem:1424  case BO_Add:1425  case BO_Sub:1426  case BO_Shl:1427  case BO_Shr:1428  case BO_LT:1429  case BO_GT:1430  case BO_LE:1431  case BO_GE:1432  case BO_EQ:1433  case BO_NE:1434  case BO_Cmp:1435  case BO_And:1436  case BO_Xor:1437  case BO_Or:1438  case BO_LAnd:1439  case BO_LOr:1440  case BO_Assign:1441  case BO_Comma:1442    llvm_unreachable("Not valid compound assignment operators");1443  }1444  llvm_unreachable("Unhandled compound assignment operator");1445}1446 1447/// Emit the computation of the specified expression of scalar type.1448mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e,1449                                           bool ignoreResultAssign) {1450  assert(e && hasScalarEvaluationKind(e->getType()) &&1451         "Invalid scalar expression to emit");1452 1453  return ScalarExprEmitter(*this, builder, ignoreResultAssign)1454      .Visit(const_cast<Expr *>(e));1455}1456 1457mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e,1458                                                   QualType promotionType) {1459  if (!promotionType.isNull())1460    return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);1461  return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));1462}1463 1464[[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {1465  // If a null pointer expression's type is the C++0x nullptr_t and1466  // the expression is not a simple literal, it must be evaluated1467  // for its potential side effects.1468  if (isa<IntegerLiteral>(e) || isa<CXXNullPtrLiteralExpr>(e))1469    return false;1470  return e->getType()->isNullPtrType();1471}1472 1473/// If \p e is a widened promoted integer, get its base (unpromoted) type.1474static std::optional<QualType>1475getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {1476  const Expr *base = e->IgnoreImpCasts();1477  if (e == base)1478    return std::nullopt;1479 1480  QualType baseTy = base->getType();1481  if (!astContext.isPromotableIntegerType(baseTy) ||1482      astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))1483    return std::nullopt;1484 1485  return baseTy;1486}1487 1488/// Check if \p e is a widened promoted integer.1489[[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,1490                                                const Expr *e) {1491  return getUnwidenedIntegerType(astContext, e).has_value();1492}1493 1494/// Check if we can skip the overflow check for \p Op.1495[[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,1496                                                   const BinOpInfo &op) {1497  assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&1498         "Expected a unary or binary operator");1499 1500  // If the binop has constant inputs and we can prove there is no overflow,1501  // we can elide the overflow check.1502  if (!op.mayHaveIntegerOverflow())1503    return true;1504 1505  // If a unary op has a widened operand, the op cannot overflow.1506  if (const auto *uo = dyn_cast<UnaryOperator>(op.e))1507    return !uo->canOverflow();1508 1509  // We usually don't need overflow checks for binops with widened operands.1510  // Multiplication with promoted unsigned operands is a special case.1511  const auto *bo = cast<BinaryOperator>(op.e);1512  std::optional<QualType> optionalLHSTy =1513      getUnwidenedIntegerType(astContext, bo->getLHS());1514  if (!optionalLHSTy)1515    return false;1516 1517  std::optional<QualType> optionalRHSTy =1518      getUnwidenedIntegerType(astContext, bo->getRHS());1519  if (!optionalRHSTy)1520    return false;1521 1522  QualType lhsTy = *optionalLHSTy;1523  QualType rhsTy = *optionalRHSTy;1524 1525  // This is the simple case: binops without unsigned multiplication, and with1526  // widened operands. No overflow check is needed here.1527  if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||1528      !lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())1529    return true;1530 1531  // For unsigned multiplication the overflow check can be elided if either one1532  // of the unpromoted types are less than half the size of the promoted type.1533  unsigned promotedSize = astContext.getTypeSize(op.e->getType());1534  return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||1535         (2 * astContext.getTypeSize(rhsTy)) < promotedSize;1536}1537 1538/// Emit pointer + index arithmetic.1539static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf,1540                                         const BinOpInfo &op,1541                                         bool isSubtraction) {1542  // Must have binary (not unary) expr here.  Unary pointer1543  // increment/decrement doesn't use this path.1544  const BinaryOperator *expr = cast<BinaryOperator>(op.e);1545 1546  mlir::Value pointer = op.lhs;1547  Expr *pointerOperand = expr->getLHS();1548  mlir::Value index = op.rhs;1549  Expr *indexOperand = expr->getRHS();1550 1551  // In the case of subtraction, the FE has ensured that the LHS is always the1552  // pointer. However, addition can have the pointer on either side. We will1553  // always have a pointer operand and an integer operand, so if the LHS wasn't1554  // a pointer, we need to swap our values.1555  if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {1556    std::swap(pointer, index);1557    std::swap(pointerOperand, indexOperand);1558  }1559  assert(mlir::isa<cir::PointerType>(pointer.getType()) &&1560         "Need a pointer operand");1561  assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");1562 1563  // Some versions of glibc and gcc use idioms (particularly in their malloc1564  // routines) that add a pointer-sized integer (known to be a pointer value)1565  // to a null pointer in order to cast the value back to an integer or as1566  // part of a pointer alignment algorithm.  This is undefined behavior, but1567  // we'd like to be able to compile programs that use it.1568  //1569  // Normally, we'd generate a GEP with a null-pointer base here in response1570  // to that code, but it's also UB to dereference a pointer created that1571  // way.  Instead (as an acknowledged hack to tolerate the idiom) we will1572  // generate a direct cast of the integer value to a pointer.1573  //1574  // The idiom (p = nullptr + N) is not met if any of the following are true:1575  //1576  //   The operation is subtraction.1577  //   The index is not pointer-sized.1578  //   The pointer type is not byte-sized.1579  //1580  if (BinaryOperator::isNullPointerArithmeticExtension(1581          cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))1582    return cgf.getBuilder().createIntToPtr(index, pointer.getType());1583 1584  // Differently from LLVM codegen, ABI bits for index sizes is handled during1585  // LLVM lowering.1586 1587  // If this is subtraction, negate the index.1588  if (isSubtraction)1589    index = cgf.getBuilder().createNeg(index);1590 1591  assert(!cir::MissingFeatures::sanitizers());1592 1593  const PointerType *pointerType =1594      pointerOperand->getType()->getAs<PointerType>();1595  if (!pointerType) {1596    cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");1597    return nullptr;1598  }1599 1600  QualType elementType = pointerType->getPointeeType();1601  if (cgf.getContext().getAsVariableArrayType(elementType)) {1602    cgf.cgm.errorNYI("variable array type");1603    return nullptr;1604  }1605 1606  if (elementType->isVoidType() || elementType->isFunctionType()) {1607    cgf.cgm.errorNYI("void* or function pointer arithmetic");1608    return nullptr;1609  }1610 1611  assert(!cir::MissingFeatures::sanitizers());1612  return cir::PtrStrideOp::create(cgf.getBuilder(),1613                                  cgf.getLoc(op.e->getExprLoc()),1614                                  pointer.getType(), pointer, index);1615}1616 1617mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {1618  const mlir::Location loc = cgf.getLoc(ops.loc);1619  if (ops.compType->isSignedIntegerOrEnumerationType()) {1620    switch (cgf.getLangOpts().getSignedOverflowBehavior()) {1621    case LangOptions::SOB_Defined:1622      if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1623        return builder.createMul(loc, ops.lhs, ops.rhs);1624      [[fallthrough]];1625    case LangOptions::SOB_Undefined:1626      if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1627        return builder.createNSWMul(loc, ops.lhs, ops.rhs);1628      [[fallthrough]];1629    case LangOptions::SOB_Trapping:1630      if (canElideOverflowCheck(cgf.getContext(), ops))1631        return builder.createNSWMul(loc, ops.lhs, ops.rhs);1632      cgf.cgm.errorNYI("sanitizers");1633    }1634  }1635  if (ops.fullType->isConstantMatrixType()) {1636    assert(!cir::MissingFeatures::matrixType());1637    cgf.cgm.errorNYI("matrix types");1638    return nullptr;1639  }1640  if (ops.compType->isUnsignedIntegerType() &&1641      cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&1642      !canElideOverflowCheck(cgf.getContext(), ops))1643    cgf.cgm.errorNYI("unsigned int overflow sanitizer");1644 1645  if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {1646    assert(!cir::MissingFeatures::cgFPOptionsRAII());1647    return builder.createFMul(loc, ops.lhs, ops.rhs);1648  }1649 1650  if (ops.isFixedPointOp()) {1651    assert(!cir::MissingFeatures::fixedPointType());1652    cgf.cgm.errorNYI("fixed point");1653    return nullptr;1654  }1655 1656  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1657                            cgf.convertType(ops.fullType), cir::BinOpKind::Mul,1658                            ops.lhs, ops.rhs);1659}1660mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {1661  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1662                            cgf.convertType(ops.fullType), cir::BinOpKind::Div,1663                            ops.lhs, ops.rhs);1664}1665mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {1666  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1667                            cgf.convertType(ops.fullType), cir::BinOpKind::Rem,1668                            ops.lhs, ops.rhs);1669}1670 1671mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {1672  if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||1673      mlir::isa<cir::PointerType>(ops.rhs.getType()))1674    return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/false);1675 1676  const mlir::Location loc = cgf.getLoc(ops.loc);1677  if (ops.compType->isSignedIntegerOrEnumerationType()) {1678    switch (cgf.getLangOpts().getSignedOverflowBehavior()) {1679    case LangOptions::SOB_Defined:1680      if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1681        return builder.createAdd(loc, ops.lhs, ops.rhs);1682      [[fallthrough]];1683    case LangOptions::SOB_Undefined:1684      if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1685        return builder.createNSWAdd(loc, ops.lhs, ops.rhs);1686      [[fallthrough]];1687    case LangOptions::SOB_Trapping:1688      if (canElideOverflowCheck(cgf.getContext(), ops))1689        return builder.createNSWAdd(loc, ops.lhs, ops.rhs);1690      cgf.cgm.errorNYI("sanitizers");1691    }1692  }1693  if (ops.fullType->isConstantMatrixType()) {1694    assert(!cir::MissingFeatures::matrixType());1695    cgf.cgm.errorNYI("matrix types");1696    return nullptr;1697  }1698 1699  if (ops.compType->isUnsignedIntegerType() &&1700      cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&1701      !canElideOverflowCheck(cgf.getContext(), ops))1702    cgf.cgm.errorNYI("unsigned int overflow sanitizer");1703 1704  if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {1705    assert(!cir::MissingFeatures::cgFPOptionsRAII());1706    return builder.createFAdd(loc, ops.lhs, ops.rhs);1707  }1708 1709  if (ops.isFixedPointOp()) {1710    assert(!cir::MissingFeatures::fixedPointType());1711    cgf.cgm.errorNYI("fixed point");1712    return {};1713  }1714 1715  return cir::BinOp::create(builder, loc, cgf.convertType(ops.fullType),1716                            cir::BinOpKind::Add, ops.lhs, ops.rhs);1717}1718 1719mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {1720  const mlir::Location loc = cgf.getLoc(ops.loc);1721  // The LHS is always a pointer if either side is.1722  if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {1723    if (ops.compType->isSignedIntegerOrEnumerationType()) {1724      switch (cgf.getLangOpts().getSignedOverflowBehavior()) {1725      case LangOptions::SOB_Defined: {1726        if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1727          return builder.createSub(loc, ops.lhs, ops.rhs);1728        [[fallthrough]];1729      }1730      case LangOptions::SOB_Undefined:1731        if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))1732          return builder.createNSWSub(loc, ops.lhs, ops.rhs);1733        [[fallthrough]];1734      case LangOptions::SOB_Trapping:1735        if (canElideOverflowCheck(cgf.getContext(), ops))1736          return builder.createNSWSub(loc, ops.lhs, ops.rhs);1737        cgf.cgm.errorNYI("sanitizers");1738      }1739    }1740 1741    if (ops.fullType->isConstantMatrixType()) {1742      assert(!cir::MissingFeatures::matrixType());1743      cgf.cgm.errorNYI("matrix types");1744      return nullptr;1745    }1746 1747    if (ops.compType->isUnsignedIntegerType() &&1748        cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&1749        !canElideOverflowCheck(cgf.getContext(), ops))1750      cgf.cgm.errorNYI("unsigned int overflow sanitizer");1751 1752    if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {1753      assert(!cir::MissingFeatures::cgFPOptionsRAII());1754      return builder.createFSub(loc, ops.lhs, ops.rhs);1755    }1756 1757    if (ops.isFixedPointOp()) {1758      assert(!cir::MissingFeatures::fixedPointType());1759      cgf.cgm.errorNYI("fixed point");1760      return {};1761    }1762 1763    return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1764                              cgf.convertType(ops.fullType),1765                              cir::BinOpKind::Sub, ops.lhs, ops.rhs);1766  }1767 1768  // If the RHS is not a pointer, then we have normal pointer1769  // arithmetic.1770  if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))1771    return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);1772 1773  // Otherwise, this is a pointer subtraction1774 1775  // Do the raw subtraction part.1776  //1777  // TODO(cir): note for LLVM lowering out of this; when expanding this into1778  // LLVM we shall take VLA's, division by element size, etc.1779  //1780  // See more in `EmitSub` in CGExprScalar.cpp.1781  assert(!cir::MissingFeatures::llvmLoweringPtrDiffConsidersPointee());1782  return cir::PtrDiffOp::create(builder, cgf.getLoc(ops.loc), cgf.ptrDiffTy,1783                                ops.lhs, ops.rhs);1784}1785 1786mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {1787  // TODO: This misses out on the sanitizer check below.1788  if (ops.isFixedPointOp()) {1789    assert(cir::MissingFeatures::fixedPointType());1790    cgf.cgm.errorNYI("fixed point");1791    return {};1792  }1793 1794  // CIR accepts shift between different types, meaning nothing special1795  // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:1796  // promote or truncate the RHS to the same size as the LHS.1797 1798  bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&1799                            ops.compType->hasSignedIntegerRepresentation() &&1800                            !cgf.getLangOpts().isSignedOverflowDefined() &&1801                            !cgf.getLangOpts().CPlusPlus20;1802  bool sanitizeUnsignedBase =1803      cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&1804      ops.compType->hasUnsignedIntegerRepresentation();1805  bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;1806  bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);1807 1808  // OpenCL 6.3j: shift values are effectively % word size of LHS.1809  if (cgf.getLangOpts().OpenCL)1810    cgf.cgm.errorNYI("opencl");1811  else if ((sanitizeBase || sanitizeExponent) &&1812           mlir::isa<cir::IntType>(ops.lhs.getType()))1813    cgf.cgm.errorNYI("sanitizers");1814 1815  return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);1816}1817 1818mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {1819  // TODO: This misses out on the sanitizer check below.1820  if (ops.isFixedPointOp()) {1821    assert(cir::MissingFeatures::fixedPointType());1822    cgf.cgm.errorNYI("fixed point");1823    return {};1824  }1825 1826  // CIR accepts shift between different types, meaning nothing special1827  // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:1828  // promote or truncate the RHS to the same size as the LHS.1829 1830  // OpenCL 6.3j: shift values are effectively % word size of LHS.1831  if (cgf.getLangOpts().OpenCL)1832    cgf.cgm.errorNYI("opencl");1833  else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&1834           mlir::isa<cir::IntType>(ops.lhs.getType()))1835    cgf.cgm.errorNYI("sanitizers");1836 1837  // Note that we don't need to distinguish unsigned treatment at this1838  // point since it will be handled later by LLVM lowering.1839  return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);1840}1841 1842mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {1843  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1844                            cgf.convertType(ops.fullType), cir::BinOpKind::And,1845                            ops.lhs, ops.rhs);1846}1847mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {1848  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1849                            cgf.convertType(ops.fullType), cir::BinOpKind::Xor,1850                            ops.lhs, ops.rhs);1851}1852mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {1853  return cir::BinOp::create(builder, cgf.getLoc(ops.loc),1854                            cgf.convertType(ops.fullType), cir::BinOpKind::Or,1855                            ops.lhs, ops.rhs);1856}1857 1858// Emit code for an explicit or implicit cast.  Implicit1859// casts have to handle a more broad range of conversions than explicit1860// casts, as they handle things like function to ptr-to-function decay1861// etc.1862mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {1863  Expr *subExpr = ce->getSubExpr();1864  QualType destTy = ce->getType();1865  CastKind kind = ce->getCastKind();1866 1867  // These cases are generally not written to ignore the result of evaluating1868  // their sub-expressions, so we clear this now.1869  ignoreResultAssign = false;1870 1871  switch (kind) {1872  case clang::CK_Dependent:1873    llvm_unreachable("dependent cast kind in CIR gen!");1874  case clang::CK_BuiltinFnToFnPtr:1875    llvm_unreachable("builtin functions are handled elsewhere");1876 1877  case CK_CPointerToObjCPointerCast:1878  case CK_BlockPointerToObjCPointerCast:1879  case CK_AnyPointerToBlockPointerCast:1880  case CK_BitCast: {1881    mlir::Value src = Visit(const_cast<Expr *>(subExpr));1882    mlir::Type dstTy = cgf.convertType(destTy);1883 1884    assert(!cir::MissingFeatures::addressSpace());1885 1886    if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))1887      cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),1888                                     "sanitizer support");1889 1890    if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)1891      cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),1892                                     "strict vtable pointers");1893 1894    // Update heapallocsite metadata when there is an explicit pointer cast.1895    assert(!cir::MissingFeatures::addHeapAllocSiteMetadata());1896 1897    // If Src is a fixed vector and Dst is a scalable vector, and both have the1898    // same element type, use the llvm.vector.insert intrinsic to perform the1899    // bitcast.1900    assert(!cir::MissingFeatures::scalableVectors());1901 1902    // If Src is a scalable vector and Dst is a fixed vector, and both have the1903    // same element type, use the llvm.vector.extract intrinsic to perform the1904    // bitcast.1905    assert(!cir::MissingFeatures::scalableVectors());1906 1907    // Perform VLAT <-> VLST bitcast through memory.1908    // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics1909    //       require the element types of the vectors to be the same, we1910    //       need to keep this around for bitcasts between VLAT <-> VLST where1911    //       the element types of the vectors are not the same, until we figure1912    //       out a better way of doing these casts.1913    assert(!cir::MissingFeatures::scalableVectors());1914 1915    return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),1916                                          src, dstTy);1917  }1918  case CK_AddressSpaceConversion: {1919    Expr::EvalResult result;1920    if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&1921        result.Val.isNullPointer()) {1922      // If e has side effect, it is emitted even if its final result is a1923      // null pointer. In that case, a DCE pass should be able to1924      // eliminate the useless instructions emitted during translating E.1925      if (result.HasSideEffects)1926        Visit(subExpr);1927      return cgf.cgm.emitNullConstant(destTy,1928                                      cgf.getLoc(subExpr->getExprLoc()));1929    }1930 1931    clang::QualType srcTy = subExpr->IgnoreImpCasts()->getType();1932    if (srcTy->isPointerType() || srcTy->isReferenceType())1933      srcTy = srcTy->getPointeeType();1934 1935    clang::LangAS srcLangAS = srcTy.getAddressSpace();1936    cir::TargetAddressSpaceAttr subExprAS;1937    if (clang::isTargetAddressSpace(srcLangAS))1938      subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);1939    else1940      cgf.cgm.errorNYI(subExpr->getSourceRange(),1941                       "non-target address space conversion");1942    // Since target may map different address spaces in AST to the same address1943    // space, an address space conversion may end up as a bitcast.1944    return cgf.cgm.getTargetCIRGenInfo().performAddrSpaceCast(1945        cgf, Visit(subExpr), subExprAS, convertType(destTy));1946  }1947 1948  case CK_AtomicToNonAtomic: {1949    cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),1950                                   "CastExpr: ", ce->getCastKindName());1951    mlir::Location loc = cgf.getLoc(subExpr->getSourceRange());1952    return cgf.createDummyValue(loc, destTy);1953  }1954  case CK_NonAtomicToAtomic:1955  case CK_UserDefinedConversion:1956    return Visit(const_cast<Expr *>(subExpr));1957  case CK_NoOp: {1958    auto v = Visit(const_cast<Expr *>(subExpr));1959    if (v) {1960      // CK_NoOp can model a pointer qualification conversion, which can remove1961      // an array bound and change the IR type.1962      // FIXME: Once pointee types are removed from IR, remove this.1963      mlir::Type t = cgf.convertType(destTy);1964      if (t != v.getType())1965        cgf.getCIRGenModule().errorNYI("pointer qualification conversion");1966    }1967    return v;1968  }1969  case CK_IntegralToPointer: {1970    mlir::Type destCIRTy = cgf.convertType(destTy);1971    mlir::Value src = Visit(const_cast<Expr *>(subExpr));1972 1973    // Properly resize by casting to an int of the same size as the pointer.1974    // Clang's IntegralToPointer includes 'bool' as the source, but in CIR1975    // 'bool' is not an integral type.  So check the source type to get the1976    // correct CIR conversion.1977    mlir::Type middleTy = cgf.cgm.getDataLayout().getIntPtrType(destCIRTy);1978    mlir::Value middleVal = builder.createCast(1979        subExpr->getType()->isBooleanType() ? cir::CastKind::bool_to_int1980                                            : cir::CastKind::integral,1981        src, middleTy);1982 1983    if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) {1984      cgf.cgm.errorNYI(subExpr->getSourceRange(),1985                       "IntegralToPointer: strict vtable pointers");1986      return {};1987    }1988 1989    return builder.createIntToPtr(middleVal, destCIRTy);1990  }1991 1992  case CK_BaseToDerived: {1993    const CXXRecordDecl *derivedClassDecl = destTy->getPointeeCXXRecordDecl();1994    assert(derivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");1995    Address base = cgf.emitPointerWithAlignment(subExpr);1996    Address derived = cgf.getAddressOfDerivedClass(1997        cgf.getLoc(ce->getSourceRange()), base, derivedClassDecl, ce->path(),1998        cgf.shouldNullCheckClassCastValue(ce));1999 2000    // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is2001    // performed and the object is not of the derived type.2002    assert(!cir::MissingFeatures::sanitizers());2003 2004    return cgf.getAsNaturalPointerTo(derived, ce->getType()->getPointeeType());2005  }2006  case CK_UncheckedDerivedToBase:2007  case CK_DerivedToBase: {2008    // The EmitPointerWithAlignment path does this fine; just discard2009    // the alignment.2010    return cgf.getAsNaturalPointerTo(cgf.emitPointerWithAlignment(ce),2011                                     ce->getType()->getPointeeType());2012  }2013  case CK_Dynamic: {2014    Address v = cgf.emitPointerWithAlignment(subExpr);2015    const auto *dce = cast<CXXDynamicCastExpr>(ce);2016    return cgf.emitDynamicCast(v, dce);2017  }2018  case CK_ArrayToPointerDecay:2019    return cgf.emitArrayToPointerDecay(subExpr).getPointer();2020 2021  case CK_NullToPointer: {2022    if (mustVisitNullValue(subExpr))2023      cgf.emitIgnoredExpr(subExpr);2024 2025    // Note that DestTy is used as the MLIR type instead of a custom2026    // nullptr type.2027    mlir::Type ty = cgf.convertType(destTy);2028    return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));2029  }2030 2031  case CK_LValueToRValue:2032    assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));2033    assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");2034    return Visit(const_cast<Expr *>(subExpr));2035 2036  case CK_IntegralCast: {2037    ScalarConversionOpts opts;2038    if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {2039      if (!ice->isPartOfExplicitCast())2040        opts = ScalarConversionOpts(cgf.sanOpts);2041    }2042    return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,2043                                ce->getExprLoc(), opts);2044  }2045 2046  case CK_FloatingComplexToReal:2047  case CK_IntegralComplexToReal:2048  case CK_FloatingComplexToBoolean:2049  case CK_IntegralComplexToBoolean: {2050    mlir::Value value = cgf.emitComplexExpr(subExpr);2051    return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,2052                                         kind, destTy);2053  }2054 2055  case CK_FloatingRealToComplex:2056  case CK_FloatingComplexCast:2057  case CK_IntegralRealToComplex:2058  case CK_IntegralComplexCast:2059  case CK_IntegralComplexToFloatingComplex:2060  case CK_FloatingComplexToIntegralComplex:2061    llvm_unreachable("scalar cast to non-scalar value");2062 2063  case CK_PointerToIntegral: {2064    assert(!destTy->isBooleanType() && "bool should use PointerToBool");2065    if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)2066      cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),2067                                     "strict vtable pointers");2068    return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));2069  }2070  case CK_ToVoid:2071    cgf.emitIgnoredExpr(subExpr);2072    return {};2073 2074  case CK_IntegralToFloating:2075  case CK_FloatingToIntegral:2076  case CK_FloatingCast:2077  case CK_FixedPointToFloating:2078  case CK_FloatingToFixedPoint: {2079    if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {2080      cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),2081                                     "fixed point casts");2082      return {};2083    }2084    assert(!cir::MissingFeatures::cgFPOptionsRAII());2085    return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,2086                                ce->getExprLoc());2087  }2088 2089  case CK_IntegralToBoolean:2090    return emitIntToBoolConversion(Visit(subExpr),2091                                   cgf.getLoc(ce->getSourceRange()));2092 2093  case CK_PointerToBoolean:2094    return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());2095  case CK_FloatingToBoolean:2096    return emitFloatToBoolConversion(Visit(subExpr),2097                                     cgf.getLoc(subExpr->getExprLoc()));2098  case CK_MemberPointerToBoolean: {2099    mlir::Value memPtr = Visit(subExpr);2100    return builder.createCast(cgf.getLoc(ce->getSourceRange()),2101                              cir::CastKind::member_ptr_to_bool, memPtr,2102                              cgf.convertType(destTy));2103  }2104 2105  case CK_VectorSplat: {2106    // Create a vector object and fill all elements with the same scalar value.2107    assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");2108    return cir::VecSplatOp::create(builder,2109                                   cgf.getLoc(subExpr->getSourceRange()),2110                                   cgf.convertType(destTy), Visit(subExpr));2111  }2112  case CK_FunctionToPointerDecay:2113    return cgf.emitLValue(subExpr).getPointer();2114 2115  default:2116    cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),2117                                   "CastExpr: ", ce->getCastKindName());2118  }2119  return {};2120}2121 2122mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {2123  if (e->getCallReturnType(cgf.getContext())->isReferenceType())2124    return emitLoadOfLValue(e);2125 2126  auto v = cgf.emitCallExpr(e).getValue();2127  assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());2128  return v;2129}2130 2131mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {2132  // TODO(cir): The classic codegen calls tryEmitAsConstant() here. Folding2133  // constants sound like work for MLIR optimizers, but we'll keep an assertion2134  // for now.2135  assert(!cir::MissingFeatures::tryEmitAsConstant());2136  Expr::EvalResult result;2137  if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {2138    llvm::APSInt value = result.Val.getInt();2139    cgf.emitIgnoredExpr(e->getBase());2140    return builder.getConstInt(cgf.getLoc(e->getExprLoc()), value);2141  }2142  return emitLoadOfLValue(e);2143}2144 2145mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {2146  const unsigned numInitElements = e->getNumInits();2147 2148  [[maybe_unused]] const bool ignore = std::exchange(ignoreResultAssign, false);2149  assert((ignore == false ||2150          (numInitElements == 0 && e->getType()->isVoidType())) &&2151         "init list ignored");2152 2153  if (e->hadArrayRangeDesignator()) {2154    cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");2155    return {};2156  }2157 2158  if (e->getType()->isVectorType()) {2159    const auto vectorType =2160        mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));2161 2162    SmallVector<mlir::Value, 16> elements;2163    for (Expr *init : e->inits()) {2164      elements.push_back(Visit(init));2165    }2166 2167    // Zero-initialize any remaining values.2168    if (numInitElements < vectorType.getSize()) {2169      const mlir::Value zeroValue = cgf.getBuilder().getNullValue(2170          vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));2171      std::fill_n(std::back_inserter(elements),2172                  vectorType.getSize() - numInitElements, zeroValue);2173    }2174 2175    return cir::VecCreateOp::create(cgf.getBuilder(),2176                                    cgf.getLoc(e->getSourceRange()), vectorType,2177                                    elements);2178  }2179 2180  // C++11 value-initialization for the scalar.2181  if (numInitElements == 0)2182    return emitNullValue(e->getType(), cgf.getLoc(e->getExprLoc()));2183 2184  return Visit(e->getInit(0));2185}2186 2187mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,2188                                                 QualType srcTy, QualType dstTy,2189                                                 SourceLocation loc) {2190  assert(CIRGenFunction::hasScalarEvaluationKind(srcTy) &&2191         CIRGenFunction::hasScalarEvaluationKind(dstTy) &&2192         "Invalid scalar expression to emit");2193  return ScalarExprEmitter(*this, builder)2194      .emitScalarConversion(src, srcTy, dstTy, loc);2195}2196 2197mlir::Value CIRGenFunction::emitComplexToScalarConversion(mlir::Value src,2198                                                          QualType srcTy,2199                                                          QualType dstTy,2200                                                          SourceLocation loc) {2201  assert(srcTy->isAnyComplexType() && hasScalarEvaluationKind(dstTy) &&2202         "Invalid complex -> scalar conversion");2203 2204  QualType complexElemTy = srcTy->castAs<ComplexType>()->getElementType();2205  if (dstTy->isBooleanType()) {2206    auto kind = complexElemTy->isFloatingType()2207                    ? cir::CastKind::float_complex_to_bool2208                    : cir::CastKind::int_complex_to_bool;2209    return builder.createCast(getLoc(loc), kind, src, convertType(dstTy));2210  }2211 2212  auto kind = complexElemTy->isFloatingType()2213                  ? cir::CastKind::float_complex_to_real2214                  : cir::CastKind::int_complex_to_real;2215  mlir::Value real =2216      builder.createCast(getLoc(loc), kind, src, convertType(complexElemTy));2217  return emitScalarConversion(real, complexElemTy, dstTy, loc);2218}2219 2220mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {2221  // Perform vector logical not on comparison with zero vector.2222  if (e->getType()->isVectorType() &&2223      e->getType()->castAs<VectorType>()->getVectorKind() ==2224          VectorKind::Generic) {2225    mlir::Value oper = Visit(e->getSubExpr());2226    mlir::Location loc = cgf.getLoc(e->getExprLoc());2227    auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());2228    auto exprVecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));2229    mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);2230    return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,2231                                 oper, zeroVec);2232  }2233 2234  // Compare operand to zero.2235  mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());2236 2237  // Invert value.2238  boolVal = builder.createNot(boolVal);2239 2240  // ZExt result to the expr type.2241  return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));2242}2243 2244mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {2245  // Try folding the offsetof to a constant.2246  Expr::EvalResult evalResult;2247  if (e->EvaluateAsInt(evalResult, cgf.getContext())) {2248    mlir::Type type = cgf.convertType(e->getType());2249    llvm::APSInt value = evalResult.Val.getInt();2250    return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);2251  }2252 2253  cgf.getCIRGenModule().errorNYI(2254      e->getSourceRange(),2255      "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");2256  return {};2257}2258 2259mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {2260  QualType promotionTy = getPromotionType(e->getSubExpr()->getType());2261  mlir::Value result = VisitRealImag(e, promotionTy);2262  if (result && !promotionTy.isNull())2263    result = emitUnPromotedValue(result, e->getType());2264  return result;2265}2266 2267mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {2268  QualType promotionTy = getPromotionType(e->getSubExpr()->getType());2269  mlir::Value result = VisitRealImag(e, promotionTy);2270  if (result && !promotionTy.isNull())2271    result = emitUnPromotedValue(result, e->getType());2272  return result;2273}2274 2275mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,2276                                             QualType promotionTy) {2277  assert(e->getOpcode() == clang::UO_Real ||2278         e->getOpcode() == clang::UO_Imag &&2279             "Invalid UnaryOp kind for ComplexType Real or Imag");2280 2281  Expr *op = e->getSubExpr();2282  mlir::Location loc = cgf.getLoc(e->getExprLoc());2283  if (op->getType()->isAnyComplexType()) {2284    // If it's an l-value, load through the appropriate subobject l-value.2285    // Note that we have to ask `e` because `op` might be an l-value that2286    // this won't work for, e.g. an Obj-C property2287    mlir::Value complex = cgf.emitComplexExpr(op);2288    if (e->isGLValue() && !promotionTy.isNull()) {2289      promotionTy = promotionTy->isAnyComplexType()2290                        ? promotionTy2291                        : cgf.getContext().getComplexType(promotionTy);2292      complex = cgf.emitPromotedValue(complex, promotionTy);2293    }2294 2295    return e->getOpcode() == clang::UO_Real2296               ? builder.createComplexReal(loc, complex)2297               : builder.createComplexImag(loc, complex);2298  }2299 2300  if (e->getOpcode() == UO_Real) {2301    mlir::Value operand = promotionTy.isNull()2302                              ? Visit(op)2303                              : cgf.emitPromotedScalarExpr(op, promotionTy);2304    return builder.createComplexReal(loc, operand);2305  }2306 2307  // __imag on a scalar returns zero. Emit the subexpr to ensure side2308  // effects are evaluated, but not the actual value.2309  mlir::Value operand;2310  if (op->isGLValue()) {2311    operand = cgf.emitLValue(op).getPointer();2312    operand = cir::LoadOp::create(builder, loc, operand);2313  } else if (!promotionTy.isNull()) {2314    operand = cgf.emitPromotedScalarExpr(op, promotionTy);2315  } else {2316    operand = cgf.emitScalarExpr(op);2317  }2318  return builder.createComplexImag(loc, operand);2319}2320 2321/// Return the size or alignment of the type of argument of the sizeof2322/// expression as an integer.2323mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(2324    const UnaryExprOrTypeTraitExpr *e) {2325  const QualType typeToSize = e->getTypeOfArgument();2326  const mlir::Location loc = cgf.getLoc(e->getSourceRange());2327  if (auto kind = e->getKind();2328      kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {2329    if (const VariableArrayType *vat =2330            cgf.getContext().getAsVariableArrayType(typeToSize)) {2331      // For _Countof, we only want to evaluate if the extent is actually2332      // variable as opposed to a multi-dimensional array whose extent is2333      // constant but whose element type is variable.2334      bool evaluateExtent = true;2335      if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {2336        evaluateExtent =2337            !vat->getSizeExpr()->isIntegerConstantExpr(cgf.getContext());2338      }2339 2340      if (evaluateExtent) {2341        if (e->isArgumentType()) {2342          // sizeof(type) - make sure to emit the VLA size.2343          cgf.emitVariablyModifiedType(typeToSize);2344        } else {2345          // C99 6.5.3.4p2: If the argument is an expression of type2346          // VLA, it is evaluated.2347          cgf.getCIRGenModule().errorNYI(2348              e->getSourceRange(),2349              "sizeof operator for VariableArrayType & evaluateExtent "2350              "ignoredExpr",2351              e->getStmtClassName());2352          return {};2353        }2354 2355        // For _Countof, we just want to return the size of a single dimension.2356        if (kind == UETT_CountOf)2357          return cgf.getVLAElements1D(vat).numElts;2358 2359        cgf.getCIRGenModule().errorNYI(2360            e->getSourceRange(),2361            "sizeof operator for VariableArrayType & evaluateExtent",2362            e->getStmtClassName());2363        return builder.getConstant(2364            loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,2365                                   -llvm::APSInt(llvm::APInt(64, 1), true)));2366      }2367    }2368  } else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {2369    cgf.getCIRGenModule().errorNYI(2370        e->getSourceRange(), "sizeof operator for OpenMpRequiredSimdAlign",2371        e->getStmtClassName());2372    return builder.getConstant(2373        loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,2374                               llvm::APSInt(llvm::APInt(64, 1), true)));2375  }2376 2377  return builder.getConstant(2378      loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,2379                             e->EvaluateKnownConstInt(cgf.getContext())));2380}2381 2382/// Return true if the specified expression is cheap enough and side-effect-free2383/// enough to evaluate unconditionally instead of conditionally.  This is used2384/// to convert control flow into selects in some cases.2385/// TODO(cir): can be shared with LLVM codegen.2386static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e,2387                                                   CIRGenFunction &cgf) {2388  // Anything that is an integer or floating point constant is fine.2389  return e->IgnoreParens()->isEvaluatable(cgf.getContext());2390 2391  // Even non-volatile automatic variables can't be evaluated unconditionally.2392  // Referencing a thread_local may cause non-trivial initialization work to2393  // occur. If we're inside a lambda and one of the variables is from the scope2394  // outside the lambda, that function may have returned already. Reading its2395  // locals is a bad idea. Also, these reads may introduce races there didn't2396  // exist in the source-level program.2397}2398 2399mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(2400    const AbstractConditionalOperator *e) {2401  CIRGenBuilderTy &builder = cgf.getBuilder();2402  mlir::Location loc = cgf.getLoc(e->getSourceRange());2403  ignoreResultAssign = false;2404 2405  // Bind the common expression if necessary.2406  CIRGenFunction::OpaqueValueMapping binding(cgf, e);2407 2408  Expr *condExpr = e->getCond();2409  Expr *lhsExpr = e->getTrueExpr();2410  Expr *rhsExpr = e->getFalseExpr();2411 2412  // If the condition constant folds and can be elided, try to avoid emitting2413  // the condition and the dead arm.2414  bool condExprBool;2415  if (cgf.constantFoldsToBool(condExpr, condExprBool)) {2416    Expr *live = lhsExpr, *dead = rhsExpr;2417    if (!condExprBool)2418      std::swap(live, dead);2419 2420    // If the dead side doesn't have labels we need, just emit the Live part.2421    if (!cgf.containsLabel(dead)) {2422      if (condExprBool)2423        assert(!cir::MissingFeatures::incrementProfileCounter());2424      mlir::Value result = Visit(live);2425 2426      // If the live part is a throw expression, it acts like it has a void2427      // type, so evaluating it returns a null Value.  However, a conditional2428      // with non-void type must return a non-null Value.2429      if (!result && !e->getType()->isVoidType()) {2430        result = builder.getConstant(2431            loc, cir::PoisonAttr::get(builder.getContext(),2432                                      cgf.convertType(e->getType())));2433      }2434 2435      return result;2436    }2437  }2438 2439  QualType condType = condExpr->getType();2440 2441  // OpenCL: If the condition is a vector, we can treat this condition like2442  // the select function.2443  if ((cgf.getLangOpts().OpenCL && condType->isVectorType()) ||2444      condType->isExtVectorType()) {2445    assert(!cir::MissingFeatures::vectorType());2446    cgf.cgm.errorNYI(e->getSourceRange(), "vector ternary op");2447  }2448 2449  if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {2450    if (!condType->isVectorType()) {2451      assert(!cir::MissingFeatures::vecTernaryOp());2452      cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");2453      return {};2454    }2455 2456    mlir::Value condValue = Visit(condExpr);2457    mlir::Value lhsValue = Visit(lhsExpr);2458    mlir::Value rhsValue = Visit(rhsExpr);2459    return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,2460                                     rhsValue);2461  }2462 2463  // If this is a really simple expression (like x ? 4 : 5), emit this as a2464  // select instead of as control flow.  We can only do this if it is cheap2465  // and safe to evaluate the LHS and RHS unconditionally.2466  if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&2467      isCheapEnoughToEvaluateUnconditionally(rhsExpr, cgf)) {2468    bool lhsIsVoid = false;2469    mlir::Value condV = cgf.evaluateExprAsBool(condExpr);2470    assert(!cir::MissingFeatures::incrementProfileCounter());2471 2472    mlir::Value lhs = Visit(lhsExpr);2473    if (!lhs) {2474      lhs = builder.getNullValue(cgf.voidTy, loc);2475      lhsIsVoid = true;2476    }2477 2478    mlir::Value rhs = Visit(rhsExpr);2479    if (lhsIsVoid) {2480      assert(!rhs && "lhs and rhs types must match");2481      rhs = builder.getNullValue(cgf.voidTy, loc);2482    }2483 2484    return builder.createSelect(loc, condV, lhs, rhs);2485  }2486 2487  mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);2488  CIRGenFunction::ConditionalEvaluation eval(cgf);2489  SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};2490  mlir::Type yieldTy{};2491 2492  auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {2493    CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};2494    cgf.curLexScope->setAsTernary();2495 2496    assert(!cir::MissingFeatures::incrementProfileCounter());2497    eval.beginEvaluation();2498    mlir::Value branch = Visit(expr);2499    eval.endEvaluation();2500 2501    if (branch) {2502      yieldTy = branch.getType();2503      cir::YieldOp::create(b, loc, branch);2504    } else {2505      // If LHS or RHS is a throw or void expression we need to patch2506      // arms as to properly match yield types.2507      insertPoints.push_back(b.saveInsertionPoint());2508    }2509  };2510 2511  mlir::Value result = cir::TernaryOp::create(2512                           builder, loc, condV,2513                           /*trueBuilder=*/2514                           [&](mlir::OpBuilder &b, mlir::Location loc) {2515                             emitBranch(b, loc, lhsExpr);2516                           },2517                           /*falseBuilder=*/2518                           [&](mlir::OpBuilder &b, mlir::Location loc) {2519                             emitBranch(b, loc, rhsExpr);2520                           })2521                           .getResult();2522 2523  if (!insertPoints.empty()) {2524    // If both arms are void, so be it.2525    if (!yieldTy)2526      yieldTy = cgf.voidTy;2527 2528    // Insert required yields.2529    for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {2530      mlir::OpBuilder::InsertionGuard guard(builder);2531      builder.restoreInsertionPoint(toInsert);2532 2533      // Block does not return: build empty yield.2534      if (mlir::isa<cir::VoidType>(yieldTy)) {2535        cir::YieldOp::create(builder, loc);2536      } else { // Block returns: set null yield value.2537        mlir::Value op0 = builder.getNullValue(yieldTy, loc);2538        cir::YieldOp::create(builder, loc, op0);2539      }2540    }2541  }2542 2543  return result;2544}2545 2546mlir::Value CIRGenFunction::emitScalarPrePostIncDec(const UnaryOperator *e,2547                                                    LValue lv,2548                                                    cir::UnaryOpKind kind,2549                                                    bool isPre) {2550  return ScalarExprEmitter(*this, builder)2551      .emitScalarPrePostIncDec(e, lv, kind, isPre);2552}2553