xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // Emit Expr nodes with scalar CIR types as CIR code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CIRGenFunction.h"
14*700637cbSDimitry Andric #include "CIRGenValue.h"
15*700637cbSDimitry Andric 
16*700637cbSDimitry Andric #include "clang/AST/Expr.h"
17*700637cbSDimitry Andric #include "clang/AST/StmtVisitor.h"
18*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric #include "mlir/IR/Location.h"
21*700637cbSDimitry Andric #include "mlir/IR/Value.h"
22*700637cbSDimitry Andric 
23*700637cbSDimitry Andric #include <cassert>
24*700637cbSDimitry Andric #include <utility>
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric using namespace clang;
27*700637cbSDimitry Andric using namespace clang::CIRGen;
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric namespace {
30*700637cbSDimitry Andric 
31*700637cbSDimitry Andric struct BinOpInfo {
32*700637cbSDimitry Andric   mlir::Value lhs;
33*700637cbSDimitry Andric   mlir::Value rhs;
34*700637cbSDimitry Andric   SourceRange loc;
35*700637cbSDimitry Andric   QualType fullType;             // Type of operands and result
36*700637cbSDimitry Andric   QualType compType;             // Type used for computations. Element type
37*700637cbSDimitry Andric                                  // for vectors, otherwise same as FullType.
38*700637cbSDimitry Andric   BinaryOperator::Opcode opcode; // Opcode of BinOp to perform
39*700637cbSDimitry Andric   FPOptions fpfeatures;
40*700637cbSDimitry Andric   const Expr *e; // Entire expr, for error unsupported.  May not be binop.
41*700637cbSDimitry Andric 
42*700637cbSDimitry Andric   /// Check if the binop computes a division or a remainder.
isDivRemOp__anon1373b7f80111::BinOpInfo43*700637cbSDimitry Andric   bool isDivRemOp() const {
44*700637cbSDimitry Andric     return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
45*700637cbSDimitry Andric            opcode == BO_RemAssign;
46*700637cbSDimitry Andric   }
47*700637cbSDimitry Andric 
48*700637cbSDimitry Andric   /// Check if the binop can result in integer overflow.
mayHaveIntegerOverflow__anon1373b7f80111::BinOpInfo49*700637cbSDimitry Andric   bool mayHaveIntegerOverflow() const {
50*700637cbSDimitry Andric     // Without constant input, we can't rule out overflow.
51*700637cbSDimitry Andric     auto lhsci = dyn_cast<cir::ConstantOp>(lhs.getDefiningOp());
52*700637cbSDimitry Andric     auto rhsci = dyn_cast<cir::ConstantOp>(rhs.getDefiningOp());
53*700637cbSDimitry Andric     if (!lhsci || !rhsci)
54*700637cbSDimitry Andric       return true;
55*700637cbSDimitry Andric 
56*700637cbSDimitry Andric     assert(!cir::MissingFeatures::mayHaveIntegerOverflow());
57*700637cbSDimitry Andric     // TODO(cir): For now we just assume that we might overflow
58*700637cbSDimitry Andric     return true;
59*700637cbSDimitry Andric   }
60*700637cbSDimitry Andric 
61*700637cbSDimitry Andric   /// Check if at least one operand is a fixed point type. In such cases,
62*700637cbSDimitry Andric   /// this operation did not follow usual arithmetic conversion and both
63*700637cbSDimitry Andric   /// operands might not be of the same type.
isFixedPointOp__anon1373b7f80111::BinOpInfo64*700637cbSDimitry Andric   bool isFixedPointOp() const {
65*700637cbSDimitry Andric     // We cannot simply check the result type since comparison operations
66*700637cbSDimitry Andric     // return an int.
67*700637cbSDimitry Andric     if (const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
68*700637cbSDimitry Andric       QualType lhstype = binOp->getLHS()->getType();
69*700637cbSDimitry Andric       QualType rhstype = binOp->getRHS()->getType();
70*700637cbSDimitry Andric       return lhstype->isFixedPointType() || rhstype->isFixedPointType();
71*700637cbSDimitry Andric     }
72*700637cbSDimitry Andric     if (const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
73*700637cbSDimitry Andric       return unop->getSubExpr()->getType()->isFixedPointType();
74*700637cbSDimitry Andric     return false;
75*700637cbSDimitry Andric   }
76*700637cbSDimitry Andric };
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
79*700637cbSDimitry Andric   CIRGenFunction &cgf;
80*700637cbSDimitry Andric   CIRGenBuilderTy &builder;
81*700637cbSDimitry Andric   bool ignoreResultAssign;
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric public:
ScalarExprEmitter(CIRGenFunction & cgf,CIRGenBuilderTy & builder)84*700637cbSDimitry Andric   ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder)
85*700637cbSDimitry Andric       : cgf(cgf), builder(builder) {}
86*700637cbSDimitry Andric 
87*700637cbSDimitry Andric   //===--------------------------------------------------------------------===//
88*700637cbSDimitry Andric   //                               Utilities
89*700637cbSDimitry Andric   //===--------------------------------------------------------------------===//
90*700637cbSDimitry Andric 
emitPromotedValue(mlir::Value result,QualType promotionType)91*700637cbSDimitry Andric   mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
92*700637cbSDimitry Andric     return builder.createFloatingCast(result, cgf.convertType(promotionType));
93*700637cbSDimitry Andric   }
94*700637cbSDimitry Andric 
emitUnPromotedValue(mlir::Value result,QualType exprType)95*700637cbSDimitry Andric   mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
96*700637cbSDimitry Andric     return builder.createFloatingCast(result, cgf.convertType(exprType));
97*700637cbSDimitry Andric   }
98*700637cbSDimitry Andric 
99*700637cbSDimitry Andric   mlir::Value emitPromoted(const Expr *e, QualType promotionType);
100*700637cbSDimitry Andric 
maybePromoteBoolResult(mlir::Value value,mlir::Type dstTy) const101*700637cbSDimitry Andric   mlir::Value maybePromoteBoolResult(mlir::Value value,
102*700637cbSDimitry Andric                                      mlir::Type dstTy) const {
103*700637cbSDimitry Andric     if (mlir::isa<cir::IntType>(dstTy))
104*700637cbSDimitry Andric       return builder.createBoolToInt(value, dstTy);
105*700637cbSDimitry Andric     if (mlir::isa<cir::BoolType>(dstTy))
106*700637cbSDimitry Andric       return value;
107*700637cbSDimitry Andric     llvm_unreachable("Can only promote integer or boolean types");
108*700637cbSDimitry Andric   }
109*700637cbSDimitry Andric 
110*700637cbSDimitry Andric   //===--------------------------------------------------------------------===//
111*700637cbSDimitry Andric   //                            Visitor Methods
112*700637cbSDimitry Andric   //===--------------------------------------------------------------------===//
113*700637cbSDimitry Andric 
Visit(Expr * e)114*700637cbSDimitry Andric   mlir::Value Visit(Expr *e) {
115*700637cbSDimitry Andric     return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
116*700637cbSDimitry Andric   }
117*700637cbSDimitry Andric 
VisitStmt(Stmt * s)118*700637cbSDimitry Andric   mlir::Value VisitStmt(Stmt *s) {
119*700637cbSDimitry Andric     llvm_unreachable("Statement passed to ScalarExprEmitter");
120*700637cbSDimitry Andric   }
121*700637cbSDimitry Andric 
VisitExpr(Expr * e)122*700637cbSDimitry Andric   mlir::Value VisitExpr(Expr *e) {
123*700637cbSDimitry Andric     cgf.getCIRGenModule().errorNYI(
124*700637cbSDimitry Andric         e->getSourceRange(), "scalar expression kind: ", e->getStmtClassName());
125*700637cbSDimitry Andric     return {};
126*700637cbSDimitry Andric   }
127*700637cbSDimitry Andric 
VisitPackIndexingExpr(PackIndexingExpr * e)128*700637cbSDimitry Andric   mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
129*700637cbSDimitry Andric     return Visit(e->getSelectedExpr());
130*700637cbSDimitry Andric   }
131*700637cbSDimitry Andric 
VisitParenExpr(ParenExpr * pe)132*700637cbSDimitry Andric   mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
133*700637cbSDimitry Andric 
VisitGenericSelectionExpr(GenericSelectionExpr * ge)134*700637cbSDimitry Andric   mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
135*700637cbSDimitry Andric     return Visit(ge->getResultExpr());
136*700637cbSDimitry Andric   }
137*700637cbSDimitry Andric 
138*700637cbSDimitry Andric   /// Emits the address of the l-value, then loads and returns the result.
emitLoadOfLValue(const Expr * e)139*700637cbSDimitry Andric   mlir::Value emitLoadOfLValue(const Expr *e) {
140*700637cbSDimitry Andric     LValue lv = cgf.emitLValue(e);
141*700637cbSDimitry Andric     // FIXME: add some akin to EmitLValueAlignmentAssumption(E, V);
142*700637cbSDimitry Andric     return cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
143*700637cbSDimitry Andric   }
144*700637cbSDimitry Andric 
emitLoadOfLValue(LValue lv,SourceLocation loc)145*700637cbSDimitry Andric   mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
146*700637cbSDimitry Andric     return cgf.emitLoadOfLValue(lv, loc).getValue();
147*700637cbSDimitry Andric   }
148*700637cbSDimitry Andric 
149*700637cbSDimitry Andric   // l-values
VisitDeclRefExpr(DeclRefExpr * e)150*700637cbSDimitry Andric   mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
151*700637cbSDimitry Andric     if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
152*700637cbSDimitry Andric       return cgf.emitScalarConstant(constant, e);
153*700637cbSDimitry Andric 
154*700637cbSDimitry Andric     return emitLoadOfLValue(e);
155*700637cbSDimitry Andric   }
156*700637cbSDimitry Andric 
VisitIntegerLiteral(const IntegerLiteral * e)157*700637cbSDimitry Andric   mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {
158*700637cbSDimitry Andric     mlir::Type type = cgf.convertType(e->getType());
159*700637cbSDimitry Andric     return builder.create<cir::ConstantOp>(
160*700637cbSDimitry Andric         cgf.getLoc(e->getExprLoc()), cir::IntAttr::get(type, e->getValue()));
161*700637cbSDimitry Andric   }
162*700637cbSDimitry Andric 
VisitFloatingLiteral(const FloatingLiteral * e)163*700637cbSDimitry Andric   mlir::Value VisitFloatingLiteral(const FloatingLiteral *e) {
164*700637cbSDimitry Andric     mlir::Type type = cgf.convertType(e->getType());
165*700637cbSDimitry Andric     assert(mlir::isa<cir::FPTypeInterface>(type) &&
166*700637cbSDimitry Andric            "expect floating-point type");
167*700637cbSDimitry Andric     return builder.create<cir::ConstantOp>(
168*700637cbSDimitry Andric         cgf.getLoc(e->getExprLoc()), cir::FPAttr::get(type, e->getValue()));
169*700637cbSDimitry Andric   }
170*700637cbSDimitry Andric 
VisitCharacterLiteral(const CharacterLiteral * e)171*700637cbSDimitry Andric   mlir::Value VisitCharacterLiteral(const CharacterLiteral *e) {
172*700637cbSDimitry Andric     mlir::Type ty = cgf.convertType(e->getType());
173*700637cbSDimitry Andric     auto init = cir::IntAttr::get(ty, e->getValue());
174*700637cbSDimitry Andric     return builder.create<cir::ConstantOp>(cgf.getLoc(e->getExprLoc()), init);
175*700637cbSDimitry Andric   }
176*700637cbSDimitry Andric 
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * e)177*700637cbSDimitry Andric   mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {
178*700637cbSDimitry Andric     return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
179*700637cbSDimitry Andric   }
180*700637cbSDimitry Andric 
181*700637cbSDimitry Andric   mlir::Value VisitCastExpr(CastExpr *e);
182*700637cbSDimitry Andric   mlir::Value VisitCallExpr(const CallExpr *e);
183*700637cbSDimitry Andric 
VisitArraySubscriptExpr(ArraySubscriptExpr * e)184*700637cbSDimitry Andric   mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
185*700637cbSDimitry Andric     if (e->getBase()->getType()->isVectorType()) {
186*700637cbSDimitry Andric       assert(!cir::MissingFeatures::scalableVectors());
187*700637cbSDimitry Andric 
188*700637cbSDimitry Andric       const mlir::Location loc = cgf.getLoc(e->getSourceRange());
189*700637cbSDimitry Andric       const mlir::Value vecValue = Visit(e->getBase());
190*700637cbSDimitry Andric       const mlir::Value indexValue = Visit(e->getIdx());
191*700637cbSDimitry Andric       return cgf.builder.create<cir::VecExtractOp>(loc, vecValue, indexValue);
192*700637cbSDimitry Andric     }
193*700637cbSDimitry Andric     // Just load the lvalue formed by the subscript expression.
194*700637cbSDimitry Andric     return emitLoadOfLValue(e);
195*700637cbSDimitry Andric   }
196*700637cbSDimitry Andric 
VisitShuffleVectorExpr(ShuffleVectorExpr * e)197*700637cbSDimitry Andric   mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
198*700637cbSDimitry Andric     if (e->getNumSubExprs() == 2) {
199*700637cbSDimitry Andric       // The undocumented form of __builtin_shufflevector.
200*700637cbSDimitry Andric       mlir::Value inputVec = Visit(e->getExpr(0));
201*700637cbSDimitry Andric       mlir::Value indexVec = Visit(e->getExpr(1));
202*700637cbSDimitry Andric       return cgf.builder.create<cir::VecShuffleDynamicOp>(
203*700637cbSDimitry Andric           cgf.getLoc(e->getSourceRange()), inputVec, indexVec);
204*700637cbSDimitry Andric     }
205*700637cbSDimitry Andric 
206*700637cbSDimitry Andric     mlir::Value vec1 = Visit(e->getExpr(0));
207*700637cbSDimitry Andric     mlir::Value vec2 = Visit(e->getExpr(1));
208*700637cbSDimitry Andric 
209*700637cbSDimitry Andric     // The documented form of __builtin_shufflevector, where the indices are
210*700637cbSDimitry Andric     // a variable number of integer constants. The constants will be stored
211*700637cbSDimitry Andric     // in an ArrayAttr.
212*700637cbSDimitry Andric     SmallVector<mlir::Attribute, 8> indices;
213*700637cbSDimitry Andric     for (unsigned i = 2; i < e->getNumSubExprs(); ++i) {
214*700637cbSDimitry Andric       indices.push_back(
215*700637cbSDimitry Andric           cir::IntAttr::get(cgf.builder.getSInt64Ty(),
216*700637cbSDimitry Andric                             e->getExpr(i)
217*700637cbSDimitry Andric                                 ->EvaluateKnownConstInt(cgf.getContext())
218*700637cbSDimitry Andric                                 .getSExtValue()));
219*700637cbSDimitry Andric     }
220*700637cbSDimitry Andric 
221*700637cbSDimitry Andric     return cgf.builder.create<cir::VecShuffleOp>(
222*700637cbSDimitry Andric         cgf.getLoc(e->getSourceRange()), cgf.convertType(e->getType()), vec1,
223*700637cbSDimitry Andric         vec2, cgf.builder.getArrayAttr(indices));
224*700637cbSDimitry Andric   }
225*700637cbSDimitry Andric 
VisitConvertVectorExpr(ConvertVectorExpr * e)226*700637cbSDimitry Andric   mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
227*700637cbSDimitry Andric     // __builtin_convertvector is an element-wise cast, and is implemented as a
228*700637cbSDimitry Andric     // regular cast. The back end handles casts of vectors correctly.
229*700637cbSDimitry Andric     return emitScalarConversion(Visit(e->getSrcExpr()),
230*700637cbSDimitry Andric                                 e->getSrcExpr()->getType(), e->getType(),
231*700637cbSDimitry Andric                                 e->getSourceRange().getBegin());
232*700637cbSDimitry Andric   }
233*700637cbSDimitry Andric 
234*700637cbSDimitry Andric   mlir::Value VisitMemberExpr(MemberExpr *e);
235*700637cbSDimitry Andric 
236*700637cbSDimitry Andric   mlir::Value VisitInitListExpr(InitListExpr *e);
237*700637cbSDimitry Andric 
VisitExplicitCastExpr(ExplicitCastExpr * e)238*700637cbSDimitry Andric   mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
239*700637cbSDimitry Andric     return VisitCastExpr(e);
240*700637cbSDimitry Andric   }
241*700637cbSDimitry Andric 
VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr * e)242*700637cbSDimitry Andric   mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
243*700637cbSDimitry Andric     return cgf.cgm.emitNullConstant(e->getType(),
244*700637cbSDimitry Andric                                     cgf.getLoc(e->getSourceRange()));
245*700637cbSDimitry Andric   }
246*700637cbSDimitry Andric 
247*700637cbSDimitry Andric   /// Perform a pointer to boolean conversion.
emitPointerToBoolConversion(mlir::Value v,QualType qt)248*700637cbSDimitry Andric   mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
249*700637cbSDimitry Andric     // TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM.
250*700637cbSDimitry Andric     // We might want to have a separate pass for these types of conversions.
251*700637cbSDimitry Andric     return cgf.getBuilder().createPtrToBoolCast(v);
252*700637cbSDimitry Andric   }
253*700637cbSDimitry Andric 
emitFloatToBoolConversion(mlir::Value src,mlir::Location loc)254*700637cbSDimitry Andric   mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
255*700637cbSDimitry Andric     cir::BoolType boolTy = builder.getBoolTy();
256*700637cbSDimitry Andric     return builder.create<cir::CastOp>(loc, boolTy,
257*700637cbSDimitry Andric                                        cir::CastKind::float_to_bool, src);
258*700637cbSDimitry Andric   }
259*700637cbSDimitry Andric 
emitIntToBoolConversion(mlir::Value srcVal,mlir::Location loc)260*700637cbSDimitry Andric   mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
261*700637cbSDimitry Andric     // Because of the type rules of C, we often end up computing a
262*700637cbSDimitry Andric     // logical value, then zero extending it to int, then wanting it
263*700637cbSDimitry Andric     // as a logical value again.
264*700637cbSDimitry Andric     // TODO: optimize this common case here or leave it for later
265*700637cbSDimitry Andric     // CIR passes?
266*700637cbSDimitry Andric     cir::BoolType boolTy = builder.getBoolTy();
267*700637cbSDimitry Andric     return builder.create<cir::CastOp>(loc, boolTy, cir::CastKind::int_to_bool,
268*700637cbSDimitry Andric                                        srcVal);
269*700637cbSDimitry Andric   }
270*700637cbSDimitry Andric 
271*700637cbSDimitry Andric   /// Convert the specified expression value to a boolean (!cir.bool) truth
272*700637cbSDimitry Andric   /// value. This is equivalent to "Val != 0".
emitConversionToBool(mlir::Value src,QualType srcType,mlir::Location loc)273*700637cbSDimitry Andric   mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
274*700637cbSDimitry Andric                                    mlir::Location loc) {
275*700637cbSDimitry Andric     assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs");
276*700637cbSDimitry Andric 
277*700637cbSDimitry Andric     if (srcType->isRealFloatingType())
278*700637cbSDimitry Andric       return emitFloatToBoolConversion(src, loc);
279*700637cbSDimitry Andric 
280*700637cbSDimitry Andric     if (llvm::isa<MemberPointerType>(srcType)) {
281*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion");
282*700637cbSDimitry Andric       return builder.getFalse(loc);
283*700637cbSDimitry Andric     }
284*700637cbSDimitry Andric 
285*700637cbSDimitry Andric     if (srcType->isIntegerType())
286*700637cbSDimitry Andric       return emitIntToBoolConversion(src, loc);
287*700637cbSDimitry Andric 
288*700637cbSDimitry Andric     assert(::mlir::isa<cir::PointerType>(src.getType()));
289*700637cbSDimitry Andric     return emitPointerToBoolConversion(src, srcType);
290*700637cbSDimitry Andric   }
291*700637cbSDimitry Andric 
292*700637cbSDimitry Andric   // Emit a conversion from the specified type to the specified destination
293*700637cbSDimitry Andric   // type, both of which are CIR scalar types.
294*700637cbSDimitry Andric   struct ScalarConversionOpts {
295*700637cbSDimitry Andric     bool treatBooleanAsSigned;
296*700637cbSDimitry Andric     bool emitImplicitIntegerTruncationChecks;
297*700637cbSDimitry Andric     bool emitImplicitIntegerSignChangeChecks;
298*700637cbSDimitry Andric 
ScalarConversionOpts__anon1373b7f80111::ScalarExprEmitter::ScalarConversionOpts299*700637cbSDimitry Andric     ScalarConversionOpts()
300*700637cbSDimitry Andric         : treatBooleanAsSigned(false),
301*700637cbSDimitry Andric           emitImplicitIntegerTruncationChecks(false),
302*700637cbSDimitry Andric           emitImplicitIntegerSignChangeChecks(false) {}
303*700637cbSDimitry Andric 
ScalarConversionOpts__anon1373b7f80111::ScalarExprEmitter::ScalarConversionOpts304*700637cbSDimitry Andric     ScalarConversionOpts(clang::SanitizerSet sanOpts)
305*700637cbSDimitry Andric         : treatBooleanAsSigned(false),
306*700637cbSDimitry Andric           emitImplicitIntegerTruncationChecks(
307*700637cbSDimitry Andric               sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
308*700637cbSDimitry Andric           emitImplicitIntegerSignChangeChecks(
309*700637cbSDimitry Andric               sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
310*700637cbSDimitry Andric   };
311*700637cbSDimitry Andric 
312*700637cbSDimitry Andric   // Conversion from bool, integral, or floating-point to integral or
313*700637cbSDimitry Andric   // floating-point. Conversions involving other types are handled elsewhere.
314*700637cbSDimitry Andric   // Conversion to bool is handled elsewhere because that's a comparison against
315*700637cbSDimitry Andric   // zero, not a simple cast. This handles both individual scalars and vectors.
emitScalarCast(mlir::Value src,QualType srcType,QualType dstType,mlir::Type srcTy,mlir::Type dstTy,ScalarConversionOpts opts)316*700637cbSDimitry Andric   mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
317*700637cbSDimitry Andric                              QualType dstType, mlir::Type srcTy,
318*700637cbSDimitry Andric                              mlir::Type dstTy, ScalarConversionOpts opts) {
319*700637cbSDimitry Andric     assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
320*700637cbSDimitry Andric            "Internal error: matrix types not handled by this function.");
321*700637cbSDimitry Andric     assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
322*700637cbSDimitry Andric              mlir::isa<mlir::IntegerType>(dstTy)) &&
323*700637cbSDimitry Andric            "Obsolete code. Don't use mlir::IntegerType with CIR.");
324*700637cbSDimitry Andric 
325*700637cbSDimitry Andric     mlir::Type fullDstTy = dstTy;
326*700637cbSDimitry Andric     if (mlir::isa<cir::VectorType>(srcTy) &&
327*700637cbSDimitry Andric         mlir::isa<cir::VectorType>(dstTy)) {
328*700637cbSDimitry Andric       // Use the element types of the vectors to figure out the CastKind.
329*700637cbSDimitry Andric       srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
330*700637cbSDimitry Andric       dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
331*700637cbSDimitry Andric     }
332*700637cbSDimitry Andric 
333*700637cbSDimitry Andric     std::optional<cir::CastKind> castKind;
334*700637cbSDimitry Andric 
335*700637cbSDimitry Andric     if (mlir::isa<cir::BoolType>(srcTy)) {
336*700637cbSDimitry Andric       if (opts.treatBooleanAsSigned)
337*700637cbSDimitry Andric         cgf.getCIRGenModule().errorNYI("signed bool");
338*700637cbSDimitry Andric       if (cgf.getBuilder().isInt(dstTy))
339*700637cbSDimitry Andric         castKind = cir::CastKind::bool_to_int;
340*700637cbSDimitry Andric       else if (mlir::isa<cir::FPTypeInterface>(dstTy))
341*700637cbSDimitry Andric         castKind = cir::CastKind::bool_to_float;
342*700637cbSDimitry Andric       else
343*700637cbSDimitry Andric         llvm_unreachable("Internal error: Cast to unexpected type");
344*700637cbSDimitry Andric     } else if (cgf.getBuilder().isInt(srcTy)) {
345*700637cbSDimitry Andric       if (cgf.getBuilder().isInt(dstTy))
346*700637cbSDimitry Andric         castKind = cir::CastKind::integral;
347*700637cbSDimitry Andric       else if (mlir::isa<cir::FPTypeInterface>(dstTy))
348*700637cbSDimitry Andric         castKind = cir::CastKind::int_to_float;
349*700637cbSDimitry Andric       else
350*700637cbSDimitry Andric         llvm_unreachable("Internal error: Cast to unexpected type");
351*700637cbSDimitry Andric     } else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
352*700637cbSDimitry Andric       if (cgf.getBuilder().isInt(dstTy)) {
353*700637cbSDimitry Andric         // If we can't recognize overflow as undefined behavior, assume that
354*700637cbSDimitry Andric         // overflow saturates. This protects against normal optimizations if we
355*700637cbSDimitry Andric         // are compiling with non-standard FP semantics.
356*700637cbSDimitry Andric         if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
357*700637cbSDimitry Andric           cgf.getCIRGenModule().errorNYI("strict float cast overflow");
358*700637cbSDimitry Andric         assert(!cir::MissingFeatures::fpConstraints());
359*700637cbSDimitry Andric         castKind = cir::CastKind::float_to_int;
360*700637cbSDimitry Andric       } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
361*700637cbSDimitry Andric         // TODO: split this to createFPExt/createFPTrunc
362*700637cbSDimitry Andric         return builder.createFloatingCast(src, fullDstTy);
363*700637cbSDimitry Andric       } else {
364*700637cbSDimitry Andric         llvm_unreachable("Internal error: Cast to unexpected type");
365*700637cbSDimitry Andric       }
366*700637cbSDimitry Andric     } else {
367*700637cbSDimitry Andric       llvm_unreachable("Internal error: Cast from unexpected type");
368*700637cbSDimitry Andric     }
369*700637cbSDimitry Andric 
370*700637cbSDimitry Andric     assert(castKind.has_value() && "Internal error: CastKind not set.");
371*700637cbSDimitry Andric     return builder.create<cir::CastOp>(src.getLoc(), fullDstTy, *castKind, src);
372*700637cbSDimitry Andric   }
373*700637cbSDimitry Andric 
374*700637cbSDimitry Andric   mlir::Value
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr * e)375*700637cbSDimitry Andric   VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
376*700637cbSDimitry Andric     return Visit(e->getReplacement());
377*700637cbSDimitry Andric   }
378*700637cbSDimitry Andric 
379*700637cbSDimitry Andric   mlir::Value VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *e);
380*700637cbSDimitry Andric   mlir::Value
381*700637cbSDimitry Andric   VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
382*700637cbSDimitry Andric 
383*700637cbSDimitry Andric   // Unary Operators.
VisitUnaryPostDec(const UnaryOperator * e)384*700637cbSDimitry Andric   mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
385*700637cbSDimitry Andric     LValue lv = cgf.emitLValue(e->getSubExpr());
386*700637cbSDimitry Andric     return emitScalarPrePostIncDec(e, lv, false, false);
387*700637cbSDimitry Andric   }
VisitUnaryPostInc(const UnaryOperator * e)388*700637cbSDimitry Andric   mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
389*700637cbSDimitry Andric     LValue lv = cgf.emitLValue(e->getSubExpr());
390*700637cbSDimitry Andric     return emitScalarPrePostIncDec(e, lv, true, false);
391*700637cbSDimitry Andric   }
VisitUnaryPreDec(const UnaryOperator * e)392*700637cbSDimitry Andric   mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
393*700637cbSDimitry Andric     LValue lv = cgf.emitLValue(e->getSubExpr());
394*700637cbSDimitry Andric     return emitScalarPrePostIncDec(e, lv, false, true);
395*700637cbSDimitry Andric   }
VisitUnaryPreInc(const UnaryOperator * e)396*700637cbSDimitry Andric   mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
397*700637cbSDimitry Andric     LValue lv = cgf.emitLValue(e->getSubExpr());
398*700637cbSDimitry Andric     return emitScalarPrePostIncDec(e, lv, true, true);
399*700637cbSDimitry Andric   }
emitScalarPrePostIncDec(const UnaryOperator * e,LValue lv,bool isInc,bool isPre)400*700637cbSDimitry Andric   mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
401*700637cbSDimitry Andric                                       bool isInc, bool isPre) {
402*700637cbSDimitry Andric     if (cgf.getLangOpts().OpenMP)
403*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");
404*700637cbSDimitry Andric 
405*700637cbSDimitry Andric     QualType type = e->getSubExpr()->getType();
406*700637cbSDimitry Andric 
407*700637cbSDimitry Andric     mlir::Value value;
408*700637cbSDimitry Andric     mlir::Value input;
409*700637cbSDimitry Andric 
410*700637cbSDimitry Andric     if (type->getAs<AtomicType>()) {
411*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");
412*700637cbSDimitry Andric       // TODO(cir): This is not correct, but it will produce reasonable code
413*700637cbSDimitry Andric       // until atomic operations are implemented.
414*700637cbSDimitry Andric       value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
415*700637cbSDimitry Andric       input = value;
416*700637cbSDimitry Andric     } else {
417*700637cbSDimitry Andric       value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
418*700637cbSDimitry Andric       input = value;
419*700637cbSDimitry Andric     }
420*700637cbSDimitry Andric 
421*700637cbSDimitry Andric     // NOTE: When possible, more frequent cases are handled first.
422*700637cbSDimitry Andric 
423*700637cbSDimitry Andric     // Special case of integer increment that we have to check first: bool++.
424*700637cbSDimitry Andric     // Due to promotion rules, we get:
425*700637cbSDimitry Andric     //   bool++ -> bool = bool + 1
426*700637cbSDimitry Andric     //          -> bool = (int)bool + 1
427*700637cbSDimitry Andric     //          -> bool = ((int)bool + 1 != 0)
428*700637cbSDimitry Andric     // An interesting aspect of this is that increment is always true.
429*700637cbSDimitry Andric     // Decrement does not have this property.
430*700637cbSDimitry Andric     if (isInc && type->isBooleanType()) {
431*700637cbSDimitry Andric       value = builder.getTrue(cgf.getLoc(e->getExprLoc()));
432*700637cbSDimitry Andric     } else if (type->isIntegerType()) {
433*700637cbSDimitry Andric       QualType promotedType;
434*700637cbSDimitry Andric       bool canPerformLossyDemotionCheck = false;
435*700637cbSDimitry Andric       if (cgf.getContext().isPromotableIntegerType(type)) {
436*700637cbSDimitry Andric         promotedType = cgf.getContext().getPromotedIntegerType(type);
437*700637cbSDimitry Andric         assert(promotedType != type && "Shouldn't promote to the same type.");
438*700637cbSDimitry Andric         canPerformLossyDemotionCheck = true;
439*700637cbSDimitry Andric         canPerformLossyDemotionCheck &=
440*700637cbSDimitry Andric             cgf.getContext().getCanonicalType(type) !=
441*700637cbSDimitry Andric             cgf.getContext().getCanonicalType(promotedType);
442*700637cbSDimitry Andric         canPerformLossyDemotionCheck &=
443*700637cbSDimitry Andric             type->isIntegerType() && promotedType->isIntegerType();
444*700637cbSDimitry Andric 
445*700637cbSDimitry Andric         // TODO(cir): Currently, we store bitwidths in CIR types only for
446*700637cbSDimitry Andric         // integers. This might also be required for other types.
447*700637cbSDimitry Andric 
448*700637cbSDimitry Andric         assert(
449*700637cbSDimitry Andric             (!canPerformLossyDemotionCheck ||
450*700637cbSDimitry Andric              type->isSignedIntegerOrEnumerationType() ||
451*700637cbSDimitry Andric              promotedType->isSignedIntegerOrEnumerationType() ||
452*700637cbSDimitry Andric              mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth() ==
453*700637cbSDimitry Andric                  mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth()) &&
454*700637cbSDimitry Andric             "The following check expects that if we do promotion to different "
455*700637cbSDimitry Andric             "underlying canonical type, at least one of the types (either "
456*700637cbSDimitry Andric             "base or promoted) will be signed, or the bitwidths will match.");
457*700637cbSDimitry Andric       }
458*700637cbSDimitry Andric 
459*700637cbSDimitry Andric       assert(!cir::MissingFeatures::sanitizers());
460*700637cbSDimitry Andric       if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
461*700637cbSDimitry Andric         value = emitIncDecConsiderOverflowBehavior(e, value, isInc);
462*700637cbSDimitry Andric       } else {
463*700637cbSDimitry Andric         cir::UnaryOpKind kind =
464*700637cbSDimitry Andric             e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
465*700637cbSDimitry Andric         // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
466*700637cbSDimitry Andric         value = emitUnaryOp(e, kind, input, /*nsw=*/false);
467*700637cbSDimitry Andric       }
468*700637cbSDimitry Andric     } else if (const PointerType *ptr = type->getAs<PointerType>()) {
469*700637cbSDimitry Andric       QualType type = ptr->getPointeeType();
470*700637cbSDimitry Andric       if (cgf.getContext().getAsVariableArrayType(type)) {
471*700637cbSDimitry Andric         // VLA types don't have constant size.
472*700637cbSDimitry Andric         cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA");
473*700637cbSDimitry Andric         return {};
474*700637cbSDimitry Andric       } else if (type->isFunctionType()) {
475*700637cbSDimitry Andric         // Arithmetic on function pointers (!) is just +-1.
476*700637cbSDimitry Andric         cgf.cgm.errorNYI(e->getSourceRange(),
477*700637cbSDimitry Andric                          "Pointer arithmetic on function pointer");
478*700637cbSDimitry Andric         return {};
479*700637cbSDimitry Andric       } else {
480*700637cbSDimitry Andric         // For everything else, we can just do a simple increment.
481*700637cbSDimitry Andric         mlir::Location loc = cgf.getLoc(e->getSourceRange());
482*700637cbSDimitry Andric         CIRGenBuilderTy &builder = cgf.getBuilder();
483*700637cbSDimitry Andric         int amount = (isInc ? 1 : -1);
484*700637cbSDimitry Andric         mlir::Value amt = builder.getSInt32(amount, loc);
485*700637cbSDimitry Andric         assert(!cir::MissingFeatures::sanitizers());
486*700637cbSDimitry Andric         value = builder.createPtrStride(loc, value, amt);
487*700637cbSDimitry Andric       }
488*700637cbSDimitry Andric     } else if (type->isVectorType()) {
489*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec vector");
490*700637cbSDimitry Andric       return {};
491*700637cbSDimitry Andric     } else if (type->isRealFloatingType()) {
492*700637cbSDimitry Andric       assert(!cir::MissingFeatures::cgFPOptionsRAII());
493*700637cbSDimitry Andric 
494*700637cbSDimitry Andric       if (type->isHalfType() &&
495*700637cbSDimitry Andric           !cgf.getContext().getLangOpts().NativeHalfType) {
496*700637cbSDimitry Andric         cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec half");
497*700637cbSDimitry Andric         return {};
498*700637cbSDimitry Andric       }
499*700637cbSDimitry Andric 
500*700637cbSDimitry Andric       if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
501*700637cbSDimitry Andric         // Create the inc/dec operation.
502*700637cbSDimitry Andric         // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
503*700637cbSDimitry Andric         cir::UnaryOpKind kind =
504*700637cbSDimitry Andric             (isInc ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec);
505*700637cbSDimitry Andric         value = emitUnaryOp(e, kind, value);
506*700637cbSDimitry Andric       } else {
507*700637cbSDimitry Andric         cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
508*700637cbSDimitry Andric         return {};
509*700637cbSDimitry Andric       }
510*700637cbSDimitry Andric     } else if (type->isFixedPointType()) {
511*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fixed point");
512*700637cbSDimitry Andric       return {};
513*700637cbSDimitry Andric     } else {
514*700637cbSDimitry Andric       assert(type->castAs<ObjCObjectPointerType>());
515*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");
516*700637cbSDimitry Andric       return {};
517*700637cbSDimitry Andric     }
518*700637cbSDimitry Andric 
519*700637cbSDimitry Andric     CIRGenFunction::SourceLocRAIIObject sourceloc{
520*700637cbSDimitry Andric         cgf, cgf.getLoc(e->getSourceRange())};
521*700637cbSDimitry Andric 
522*700637cbSDimitry Andric     // Store the updated result through the lvalue
523*700637cbSDimitry Andric     if (lv.isBitField())
524*700637cbSDimitry Andric       return cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);
525*700637cbSDimitry Andric     else
526*700637cbSDimitry Andric       cgf.emitStoreThroughLValue(RValue::get(value), lv);
527*700637cbSDimitry Andric 
528*700637cbSDimitry Andric     // If this is a postinc, return the value read from memory, otherwise use
529*700637cbSDimitry Andric     // the updated value.
530*700637cbSDimitry Andric     return isPre ? value : input;
531*700637cbSDimitry Andric   }
532*700637cbSDimitry Andric 
emitIncDecConsiderOverflowBehavior(const UnaryOperator * e,mlir::Value inVal,bool isInc)533*700637cbSDimitry Andric   mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,
534*700637cbSDimitry Andric                                                  mlir::Value inVal,
535*700637cbSDimitry Andric                                                  bool isInc) {
536*700637cbSDimitry Andric     cir::UnaryOpKind kind =
537*700637cbSDimitry Andric         e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
538*700637cbSDimitry Andric     switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
539*700637cbSDimitry Andric     case LangOptions::SOB_Defined:
540*700637cbSDimitry Andric       return emitUnaryOp(e, kind, inVal, /*nsw=*/false);
541*700637cbSDimitry Andric     case LangOptions::SOB_Undefined:
542*700637cbSDimitry Andric       assert(!cir::MissingFeatures::sanitizers());
543*700637cbSDimitry Andric       return emitUnaryOp(e, kind, inVal, /*nsw=*/true);
544*700637cbSDimitry Andric     case LangOptions::SOB_Trapping:
545*700637cbSDimitry Andric       if (!e->canOverflow())
546*700637cbSDimitry Andric         return emitUnaryOp(e, kind, inVal, /*nsw=*/true);
547*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
548*700637cbSDimitry Andric       return {};
549*700637cbSDimitry Andric     }
550*700637cbSDimitry Andric     llvm_unreachable("Unexpected signed overflow behavior kind");
551*700637cbSDimitry Andric   }
552*700637cbSDimitry Andric 
VisitUnaryAddrOf(const UnaryOperator * e)553*700637cbSDimitry Andric   mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
554*700637cbSDimitry Andric     if (llvm::isa<MemberPointerType>(e->getType())) {
555*700637cbSDimitry Andric       cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer");
556*700637cbSDimitry Andric       return builder.getNullPtr(cgf.convertType(e->getType()),
557*700637cbSDimitry Andric                                 cgf.getLoc(e->getExprLoc()));
558*700637cbSDimitry Andric     }
559*700637cbSDimitry Andric 
560*700637cbSDimitry Andric     return cgf.emitLValue(e->getSubExpr()).getPointer();
561*700637cbSDimitry Andric   }
562*700637cbSDimitry Andric 
VisitUnaryDeref(const UnaryOperator * e)563*700637cbSDimitry Andric   mlir::Value VisitUnaryDeref(const UnaryOperator *e) {
564*700637cbSDimitry Andric     if (e->getType()->isVoidType())
565*700637cbSDimitry Andric       return Visit(e->getSubExpr()); // the actual value should be unused
566*700637cbSDimitry Andric     return emitLoadOfLValue(e);
567*700637cbSDimitry Andric   }
568*700637cbSDimitry Andric 
VisitUnaryPlus(const UnaryOperator * e)569*700637cbSDimitry Andric   mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
570*700637cbSDimitry Andric     return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
571*700637cbSDimitry Andric   }
572*700637cbSDimitry Andric 
VisitUnaryMinus(const UnaryOperator * e)573*700637cbSDimitry Andric   mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
574*700637cbSDimitry Andric     return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
575*700637cbSDimitry Andric   }
576*700637cbSDimitry Andric 
emitUnaryPlusOrMinus(const UnaryOperator * e,cir::UnaryOpKind kind)577*700637cbSDimitry Andric   mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e,
578*700637cbSDimitry Andric                                    cir::UnaryOpKind kind) {
579*700637cbSDimitry Andric     ignoreResultAssign = false;
580*700637cbSDimitry Andric 
581*700637cbSDimitry Andric     QualType promotionType = getPromotionType(e->getSubExpr()->getType());
582*700637cbSDimitry Andric 
583*700637cbSDimitry Andric     mlir::Value operand;
584*700637cbSDimitry Andric     if (!promotionType.isNull())
585*700637cbSDimitry Andric       operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
586*700637cbSDimitry Andric     else
587*700637cbSDimitry Andric       operand = Visit(e->getSubExpr());
588*700637cbSDimitry Andric 
589*700637cbSDimitry Andric     bool nsw =
590*700637cbSDimitry Andric         kind == cir::UnaryOpKind::Minus && e->getType()->isSignedIntegerType();
591*700637cbSDimitry Andric 
592*700637cbSDimitry Andric     // NOTE: LLVM codegen will lower this directly to either a FNeg
593*700637cbSDimitry Andric     // or a Sub instruction.  In CIR this will be handled later in LowerToLLVM.
594*700637cbSDimitry Andric     mlir::Value result = emitUnaryOp(e, kind, operand, nsw);
595*700637cbSDimitry Andric     if (result && !promotionType.isNull())
596*700637cbSDimitry Andric       return emitUnPromotedValue(result, e->getType());
597*700637cbSDimitry Andric     return result;
598*700637cbSDimitry Andric   }
599*700637cbSDimitry Andric 
emitUnaryOp(const UnaryOperator * e,cir::UnaryOpKind kind,mlir::Value input,bool nsw=false)600*700637cbSDimitry Andric   mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind,
601*700637cbSDimitry Andric                           mlir::Value input, bool nsw = false) {
602*700637cbSDimitry Andric     return builder.create<cir::UnaryOp>(
603*700637cbSDimitry Andric         cgf.getLoc(e->getSourceRange().getBegin()), input.getType(), kind,
604*700637cbSDimitry Andric         input, nsw);
605*700637cbSDimitry Andric   }
606*700637cbSDimitry Andric 
VisitUnaryNot(const UnaryOperator * e)607*700637cbSDimitry Andric   mlir::Value VisitUnaryNot(const UnaryOperator *e) {
608*700637cbSDimitry Andric     ignoreResultAssign = false;
609*700637cbSDimitry Andric     mlir::Value op = Visit(e->getSubExpr());
610*700637cbSDimitry Andric     return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
611*700637cbSDimitry Andric   }
612*700637cbSDimitry Andric 
613*700637cbSDimitry Andric   mlir::Value VisitUnaryLNot(const UnaryOperator *e);
614*700637cbSDimitry Andric 
615*700637cbSDimitry Andric   mlir::Value VisitUnaryReal(const UnaryOperator *e);
616*700637cbSDimitry Andric 
617*700637cbSDimitry Andric   mlir::Value VisitUnaryImag(const UnaryOperator *e);
618*700637cbSDimitry Andric 
VisitCXXThisExpr(CXXThisExpr * te)619*700637cbSDimitry Andric   mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
620*700637cbSDimitry Andric 
VisitCXXNewExpr(const CXXNewExpr * e)621*700637cbSDimitry Andric   mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
622*700637cbSDimitry Andric     return cgf.emitCXXNewExpr(e);
623*700637cbSDimitry Andric   }
624*700637cbSDimitry Andric 
625*700637cbSDimitry Andric   /// Emit a conversion from the specified type to the specified destination
626*700637cbSDimitry Andric   /// type, both of which are CIR scalar types.
627*700637cbSDimitry Andric   /// TODO: do we need ScalarConversionOpts here? Should be done in another
628*700637cbSDimitry Andric   /// pass.
629*700637cbSDimitry Andric   mlir::Value
emitScalarConversion(mlir::Value src,QualType srcType,QualType dstType,SourceLocation loc,ScalarConversionOpts opts=ScalarConversionOpts ())630*700637cbSDimitry Andric   emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
631*700637cbSDimitry Andric                        SourceLocation loc,
632*700637cbSDimitry Andric                        ScalarConversionOpts opts = ScalarConversionOpts()) {
633*700637cbSDimitry Andric     // All conversions involving fixed point types should be handled by the
634*700637cbSDimitry Andric     // emitFixedPoint family functions. This is done to prevent bloating up
635*700637cbSDimitry Andric     // this function more, and although fixed point numbers are represented by
636*700637cbSDimitry Andric     // integers, we do not want to follow any logic that assumes they should be
637*700637cbSDimitry Andric     // treated as integers.
638*700637cbSDimitry Andric     // TODO(leonardchan): When necessary, add another if statement checking for
639*700637cbSDimitry Andric     // conversions to fixed point types from other types.
640*700637cbSDimitry Andric     // conversions to fixed point types from other types.
641*700637cbSDimitry Andric     if (srcType->isFixedPointType() || dstType->isFixedPointType()) {
642*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions");
643*700637cbSDimitry Andric       return {};
644*700637cbSDimitry Andric     }
645*700637cbSDimitry Andric 
646*700637cbSDimitry Andric     srcType = srcType.getCanonicalType();
647*700637cbSDimitry Andric     dstType = dstType.getCanonicalType();
648*700637cbSDimitry Andric     if (srcType == dstType) {
649*700637cbSDimitry Andric       if (opts.emitImplicitIntegerSignChangeChecks)
650*700637cbSDimitry Andric         cgf.getCIRGenModule().errorNYI(loc,
651*700637cbSDimitry Andric                                        "implicit integer sign change checks");
652*700637cbSDimitry Andric       return src;
653*700637cbSDimitry Andric     }
654*700637cbSDimitry Andric 
655*700637cbSDimitry Andric     if (dstType->isVoidType())
656*700637cbSDimitry Andric       return {};
657*700637cbSDimitry Andric 
658*700637cbSDimitry Andric     mlir::Type mlirSrcType = src.getType();
659*700637cbSDimitry Andric 
660*700637cbSDimitry Andric     // Handle conversions to bool first, they are special: comparisons against
661*700637cbSDimitry Andric     // 0.
662*700637cbSDimitry Andric     if (dstType->isBooleanType())
663*700637cbSDimitry Andric       return emitConversionToBool(src, srcType, cgf.getLoc(loc));
664*700637cbSDimitry Andric 
665*700637cbSDimitry Andric     mlir::Type mlirDstType = cgf.convertType(dstType);
666*700637cbSDimitry Andric 
667*700637cbSDimitry Andric     if (srcType->isHalfType() &&
668*700637cbSDimitry Andric         !cgf.getContext().getLangOpts().NativeHalfType) {
669*700637cbSDimitry Andric       // Cast to FP using the intrinsic if the half type itself isn't supported.
670*700637cbSDimitry Andric       if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
671*700637cbSDimitry Andric         if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
672*700637cbSDimitry Andric           cgf.getCIRGenModule().errorNYI(loc,
673*700637cbSDimitry Andric                                          "cast via llvm.convert.from.fp16");
674*700637cbSDimitry Andric       } else {
675*700637cbSDimitry Andric         // Cast to other types through float, using either the intrinsic or
676*700637cbSDimitry Andric         // FPExt, depending on whether the half type itself is supported (as
677*700637cbSDimitry Andric         // opposed to operations on half, available with NativeHalfType).
678*700637cbSDimitry Andric         if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
679*700637cbSDimitry Andric           cgf.getCIRGenModule().errorNYI(loc,
680*700637cbSDimitry Andric                                          "cast via llvm.convert.from.fp16");
681*700637cbSDimitry Andric         // FIXME(cir): For now lets pretend we shouldn't use the conversion
682*700637cbSDimitry Andric         // intrinsics and insert a cast here unconditionally.
683*700637cbSDimitry Andric         src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
684*700637cbSDimitry Andric                                  cgf.FloatTy);
685*700637cbSDimitry Andric         srcType = cgf.getContext().FloatTy;
686*700637cbSDimitry Andric         mlirSrcType = cgf.FloatTy;
687*700637cbSDimitry Andric       }
688*700637cbSDimitry Andric     }
689*700637cbSDimitry Andric 
690*700637cbSDimitry Andric     // TODO(cir): LLVM codegen ignore conversions like int -> uint,
691*700637cbSDimitry Andric     // is there anything to be done for CIR here?
692*700637cbSDimitry Andric     if (mlirSrcType == mlirDstType) {
693*700637cbSDimitry Andric       if (opts.emitImplicitIntegerSignChangeChecks)
694*700637cbSDimitry Andric         cgf.getCIRGenModule().errorNYI(loc,
695*700637cbSDimitry Andric                                        "implicit integer sign change checks");
696*700637cbSDimitry Andric       return src;
697*700637cbSDimitry Andric     }
698*700637cbSDimitry Andric 
699*700637cbSDimitry Andric     // Handle pointer conversions next: pointers can only be converted to/from
700*700637cbSDimitry Andric     // other pointers and integers. Check for pointer types in terms of LLVM, as
701*700637cbSDimitry Andric     // some native types (like Obj-C id) may map to a pointer type.
702*700637cbSDimitry Andric     if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
703*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
704*700637cbSDimitry Andric       return builder.getNullPtr(dstPT, src.getLoc());
705*700637cbSDimitry Andric     }
706*700637cbSDimitry Andric 
707*700637cbSDimitry Andric     if (isa<cir::PointerType>(mlirSrcType)) {
708*700637cbSDimitry Andric       // Must be an ptr to int cast.
709*700637cbSDimitry Andric       assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");
710*700637cbSDimitry Andric       return builder.createPtrToInt(src, mlirDstType);
711*700637cbSDimitry Andric     }
712*700637cbSDimitry Andric 
713*700637cbSDimitry Andric     // A scalar can be splatted to an extended vector of the same element type
714*700637cbSDimitry Andric     if (dstType->isExtVectorType() && !srcType->isVectorType()) {
715*700637cbSDimitry Andric       // Sema should add casts to make sure that the source expression's type
716*700637cbSDimitry Andric       // is the same as the vector's element type (sans qualifiers)
717*700637cbSDimitry Andric       assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
718*700637cbSDimitry Andric                  srcType.getTypePtr() &&
719*700637cbSDimitry Andric              "Splatted expr doesn't match with vector element type?");
720*700637cbSDimitry Andric 
721*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc, "vector splatting");
722*700637cbSDimitry Andric       return {};
723*700637cbSDimitry Andric     }
724*700637cbSDimitry Andric 
725*700637cbSDimitry Andric     if (srcType->isMatrixType() && dstType->isMatrixType()) {
726*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc,
727*700637cbSDimitry Andric                                      "matrix type to matrix type conversion");
728*700637cbSDimitry Andric       return {};
729*700637cbSDimitry Andric     }
730*700637cbSDimitry Andric     assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
731*700637cbSDimitry Andric            "Internal error: conversion between matrix type and scalar type");
732*700637cbSDimitry Andric 
733*700637cbSDimitry Andric     // Finally, we have the arithmetic types or vectors of arithmetic types.
734*700637cbSDimitry Andric     mlir::Value res = nullptr;
735*700637cbSDimitry Andric     mlir::Type resTy = mlirDstType;
736*700637cbSDimitry Andric 
737*700637cbSDimitry Andric     res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
738*700637cbSDimitry Andric 
739*700637cbSDimitry Andric     if (mlirDstType != resTy) {
740*700637cbSDimitry Andric       if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
741*700637cbSDimitry Andric         cgf.getCIRGenModule().errorNYI(loc, "cast via llvm.convert.to.fp16");
742*700637cbSDimitry Andric       }
743*700637cbSDimitry Andric       // FIXME(cir): For now we never use FP16 conversion intrinsics even if
744*700637cbSDimitry Andric       // required by the target. Change that once this is implemented
745*700637cbSDimitry Andric       res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
746*700637cbSDimitry Andric                                resTy);
747*700637cbSDimitry Andric     }
748*700637cbSDimitry Andric 
749*700637cbSDimitry Andric     if (opts.emitImplicitIntegerTruncationChecks)
750*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");
751*700637cbSDimitry Andric 
752*700637cbSDimitry Andric     if (opts.emitImplicitIntegerSignChangeChecks)
753*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(loc,
754*700637cbSDimitry Andric                                      "implicit integer sign change checks");
755*700637cbSDimitry Andric 
756*700637cbSDimitry Andric     return res;
757*700637cbSDimitry Andric   }
758*700637cbSDimitry Andric 
emitBinOps(const BinaryOperator * e,QualType promotionType=QualType ())759*700637cbSDimitry Andric   BinOpInfo emitBinOps(const BinaryOperator *e,
760*700637cbSDimitry Andric                        QualType promotionType = QualType()) {
761*700637cbSDimitry Andric     BinOpInfo result;
762*700637cbSDimitry Andric     result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
763*700637cbSDimitry Andric     result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
764*700637cbSDimitry Andric     if (!promotionType.isNull())
765*700637cbSDimitry Andric       result.fullType = promotionType;
766*700637cbSDimitry Andric     else
767*700637cbSDimitry Andric       result.fullType = e->getType();
768*700637cbSDimitry Andric     result.compType = result.fullType;
769*700637cbSDimitry Andric     if (const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
770*700637cbSDimitry Andric       result.compType = vecType->getElementType();
771*700637cbSDimitry Andric     }
772*700637cbSDimitry Andric     result.opcode = e->getOpcode();
773*700637cbSDimitry Andric     result.loc = e->getSourceRange();
774*700637cbSDimitry Andric     // TODO(cir): Result.FPFeatures
775*700637cbSDimitry Andric     assert(!cir::MissingFeatures::cgFPOptionsRAII());
776*700637cbSDimitry Andric     result.e = e;
777*700637cbSDimitry Andric     return result;
778*700637cbSDimitry Andric   }
779*700637cbSDimitry Andric 
780*700637cbSDimitry Andric   mlir::Value emitMul(const BinOpInfo &ops);
781*700637cbSDimitry Andric   mlir::Value emitDiv(const BinOpInfo &ops);
782*700637cbSDimitry Andric   mlir::Value emitRem(const BinOpInfo &ops);
783*700637cbSDimitry Andric   mlir::Value emitAdd(const BinOpInfo &ops);
784*700637cbSDimitry Andric   mlir::Value emitSub(const BinOpInfo &ops);
785*700637cbSDimitry Andric   mlir::Value emitShl(const BinOpInfo &ops);
786*700637cbSDimitry Andric   mlir::Value emitShr(const BinOpInfo &ops);
787*700637cbSDimitry Andric   mlir::Value emitAnd(const BinOpInfo &ops);
788*700637cbSDimitry Andric   mlir::Value emitXor(const BinOpInfo &ops);
789*700637cbSDimitry Andric   mlir::Value emitOr(const BinOpInfo &ops);
790*700637cbSDimitry Andric 
791*700637cbSDimitry Andric   LValue emitCompoundAssignLValue(
792*700637cbSDimitry Andric       const CompoundAssignOperator *e,
793*700637cbSDimitry Andric       mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
794*700637cbSDimitry Andric       mlir::Value &result);
795*700637cbSDimitry Andric   mlir::Value
796*700637cbSDimitry Andric   emitCompoundAssign(const CompoundAssignOperator *e,
797*700637cbSDimitry Andric                      mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
798*700637cbSDimitry Andric 
799*700637cbSDimitry Andric   // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
800*700637cbSDimitry Andric   // codegen.
getPromotionType(QualType ty)801*700637cbSDimitry Andric   QualType getPromotionType(QualType ty) {
802*700637cbSDimitry Andric     if (ty->getAs<ComplexType>()) {
803*700637cbSDimitry Andric       assert(!cir::MissingFeatures::complexType());
804*700637cbSDimitry Andric       cgf.cgm.errorNYI("promotion to complex type");
805*700637cbSDimitry Andric       return QualType();
806*700637cbSDimitry Andric     }
807*700637cbSDimitry Andric     if (ty.UseExcessPrecision(cgf.getContext())) {
808*700637cbSDimitry Andric       if (ty->getAs<VectorType>()) {
809*700637cbSDimitry Andric         assert(!cir::MissingFeatures::vectorType());
810*700637cbSDimitry Andric         cgf.cgm.errorNYI("promotion to vector type");
811*700637cbSDimitry Andric         return QualType();
812*700637cbSDimitry Andric       }
813*700637cbSDimitry Andric       return cgf.getContext().FloatTy;
814*700637cbSDimitry Andric     }
815*700637cbSDimitry Andric     return QualType();
816*700637cbSDimitry Andric   }
817*700637cbSDimitry Andric 
818*700637cbSDimitry Andric // Binary operators and binary compound assignment operators.
819*700637cbSDimitry Andric #define HANDLEBINOP(OP)                                                        \
820*700637cbSDimitry Andric   mlir::Value VisitBin##OP(const BinaryOperator *e) {                          \
821*700637cbSDimitry Andric     QualType promotionTy = getPromotionType(e->getType());                     \
822*700637cbSDimitry Andric     auto result = emit##OP(emitBinOps(e, promotionTy));                        \
823*700637cbSDimitry Andric     if (result && !promotionTy.isNull())                                       \
824*700637cbSDimitry Andric       result = emitUnPromotedValue(result, e->getType());                      \
825*700637cbSDimitry Andric     return result;                                                             \
826*700637cbSDimitry Andric   }                                                                            \
827*700637cbSDimitry Andric   mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) {          \
828*700637cbSDimitry Andric     return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP);                \
829*700637cbSDimitry Andric   }
830*700637cbSDimitry Andric 
831*700637cbSDimitry Andric   HANDLEBINOP(Mul)
HANDLEBINOP(Div)832*700637cbSDimitry Andric   HANDLEBINOP(Div)
833*700637cbSDimitry Andric   HANDLEBINOP(Rem)
834*700637cbSDimitry Andric   HANDLEBINOP(Add)
835*700637cbSDimitry Andric   HANDLEBINOP(Sub)
836*700637cbSDimitry Andric   HANDLEBINOP(Shl)
837*700637cbSDimitry Andric   HANDLEBINOP(Shr)
838*700637cbSDimitry Andric   HANDLEBINOP(And)
839*700637cbSDimitry Andric   HANDLEBINOP(Xor)
840*700637cbSDimitry Andric   HANDLEBINOP(Or)
841*700637cbSDimitry Andric #undef HANDLEBINOP
842*700637cbSDimitry Andric 
843*700637cbSDimitry Andric   mlir::Value emitCmp(const BinaryOperator *e) {
844*700637cbSDimitry Andric     const mlir::Location loc = cgf.getLoc(e->getExprLoc());
845*700637cbSDimitry Andric     mlir::Value result;
846*700637cbSDimitry Andric     QualType lhsTy = e->getLHS()->getType();
847*700637cbSDimitry Andric     QualType rhsTy = e->getRHS()->getType();
848*700637cbSDimitry Andric 
849*700637cbSDimitry Andric     auto clangCmpToCIRCmp =
850*700637cbSDimitry Andric         [](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
851*700637cbSDimitry Andric       switch (clangCmp) {
852*700637cbSDimitry Andric       case BO_LT:
853*700637cbSDimitry Andric         return cir::CmpOpKind::lt;
854*700637cbSDimitry Andric       case BO_GT:
855*700637cbSDimitry Andric         return cir::CmpOpKind::gt;
856*700637cbSDimitry Andric       case BO_LE:
857*700637cbSDimitry Andric         return cir::CmpOpKind::le;
858*700637cbSDimitry Andric       case BO_GE:
859*700637cbSDimitry Andric         return cir::CmpOpKind::ge;
860*700637cbSDimitry Andric       case BO_EQ:
861*700637cbSDimitry Andric         return cir::CmpOpKind::eq;
862*700637cbSDimitry Andric       case BO_NE:
863*700637cbSDimitry Andric         return cir::CmpOpKind::ne;
864*700637cbSDimitry Andric       default:
865*700637cbSDimitry Andric         llvm_unreachable("unsupported comparison kind for cir.cmp");
866*700637cbSDimitry Andric       }
867*700637cbSDimitry Andric     };
868*700637cbSDimitry Andric 
869*700637cbSDimitry Andric     cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
870*700637cbSDimitry Andric     if (lhsTy->getAs<MemberPointerType>()) {
871*700637cbSDimitry Andric       assert(!cir::MissingFeatures::dataMemberType());
872*700637cbSDimitry Andric       assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
873*700637cbSDimitry Andric       mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
874*700637cbSDimitry Andric       mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
875*700637cbSDimitry Andric       result = builder.createCompare(loc, kind, lhs, rhs);
876*700637cbSDimitry Andric     } else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
877*700637cbSDimitry Andric       BinOpInfo boInfo = emitBinOps(e);
878*700637cbSDimitry Andric       mlir::Value lhs = boInfo.lhs;
879*700637cbSDimitry Andric       mlir::Value rhs = boInfo.rhs;
880*700637cbSDimitry Andric 
881*700637cbSDimitry Andric       if (lhsTy->isVectorType()) {
882*700637cbSDimitry Andric         if (!e->getType()->isVectorType()) {
883*700637cbSDimitry Andric           // If AltiVec, the comparison results in a numeric type, so we use
884*700637cbSDimitry Andric           // intrinsics comparing vectors and giving 0 or 1 as a result
885*700637cbSDimitry Andric           cgf.cgm.errorNYI(loc, "AltiVec comparison");
886*700637cbSDimitry Andric         } else {
887*700637cbSDimitry Andric           // Other kinds of vectors. Element-wise comparison returning
888*700637cbSDimitry Andric           // a vector.
889*700637cbSDimitry Andric           result = builder.create<cir::VecCmpOp>(
890*700637cbSDimitry Andric               cgf.getLoc(boInfo.loc), cgf.convertType(boInfo.fullType), kind,
891*700637cbSDimitry Andric               boInfo.lhs, boInfo.rhs);
892*700637cbSDimitry Andric         }
893*700637cbSDimitry Andric       } else if (boInfo.isFixedPointOp()) {
894*700637cbSDimitry Andric         assert(!cir::MissingFeatures::fixedPointType());
895*700637cbSDimitry Andric         cgf.cgm.errorNYI(loc, "fixed point comparisons");
896*700637cbSDimitry Andric         result = builder.getBool(false, loc);
897*700637cbSDimitry Andric       } else {
898*700637cbSDimitry Andric         // integers and pointers
899*700637cbSDimitry Andric         if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
900*700637cbSDimitry Andric             mlir::isa<cir::PointerType>(lhs.getType()) &&
901*700637cbSDimitry Andric             mlir::isa<cir::PointerType>(rhs.getType())) {
902*700637cbSDimitry Andric           cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");
903*700637cbSDimitry Andric         }
904*700637cbSDimitry Andric 
905*700637cbSDimitry Andric         cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
906*700637cbSDimitry Andric         result = builder.createCompare(loc, kind, lhs, rhs);
907*700637cbSDimitry Andric       }
908*700637cbSDimitry Andric     } else {
909*700637cbSDimitry Andric       // Complex Comparison: can only be an equality comparison.
910*700637cbSDimitry Andric       assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
911*700637cbSDimitry Andric 
912*700637cbSDimitry Andric       BinOpInfo boInfo = emitBinOps(e);
913*700637cbSDimitry Andric       result = builder.create<cir::CmpOp>(loc, kind, boInfo.lhs, boInfo.rhs);
914*700637cbSDimitry Andric     }
915*700637cbSDimitry Andric 
916*700637cbSDimitry Andric     return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
917*700637cbSDimitry Andric                                 e->getExprLoc());
918*700637cbSDimitry Andric   }
919*700637cbSDimitry Andric 
920*700637cbSDimitry Andric // Comparisons.
921*700637cbSDimitry Andric #define VISITCOMP(CODE)                                                        \
922*700637cbSDimitry Andric   mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
923*700637cbSDimitry Andric   VISITCOMP(LT)
VISITCOMP(GT)924*700637cbSDimitry Andric   VISITCOMP(GT)
925*700637cbSDimitry Andric   VISITCOMP(LE)
926*700637cbSDimitry Andric   VISITCOMP(GE)
927*700637cbSDimitry Andric   VISITCOMP(EQ)
928*700637cbSDimitry Andric   VISITCOMP(NE)
929*700637cbSDimitry Andric #undef VISITCOMP
930*700637cbSDimitry Andric 
931*700637cbSDimitry Andric   mlir::Value VisitBinAssign(const BinaryOperator *e) {
932*700637cbSDimitry Andric     const bool ignore = std::exchange(ignoreResultAssign, false);
933*700637cbSDimitry Andric 
934*700637cbSDimitry Andric     mlir::Value rhs;
935*700637cbSDimitry Andric     LValue lhs;
936*700637cbSDimitry Andric 
937*700637cbSDimitry Andric     switch (e->getLHS()->getType().getObjCLifetime()) {
938*700637cbSDimitry Andric     case Qualifiers::OCL_Strong:
939*700637cbSDimitry Andric     case Qualifiers::OCL_Autoreleasing:
940*700637cbSDimitry Andric     case Qualifiers::OCL_ExplicitNone:
941*700637cbSDimitry Andric     case Qualifiers::OCL_Weak:
942*700637cbSDimitry Andric       assert(!cir::MissingFeatures::objCLifetime());
943*700637cbSDimitry Andric       break;
944*700637cbSDimitry Andric     case Qualifiers::OCL_None:
945*700637cbSDimitry Andric       // __block variables need to have the rhs evaluated first, plus this
946*700637cbSDimitry Andric       // should improve codegen just a little.
947*700637cbSDimitry Andric       rhs = Visit(e->getRHS());
948*700637cbSDimitry Andric       assert(!cir::MissingFeatures::sanitizers());
949*700637cbSDimitry Andric       // TODO(cir): This needs to be emitCheckedLValue() once we support
950*700637cbSDimitry Andric       // sanitizers
951*700637cbSDimitry Andric       lhs = cgf.emitLValue(e->getLHS());
952*700637cbSDimitry Andric 
953*700637cbSDimitry Andric       // Store the value into the LHS. Bit-fields are handled specially because
954*700637cbSDimitry Andric       // the result is altered by the store, i.e., [C99 6.5.16p1]
955*700637cbSDimitry Andric       // 'An assignment expression has the value of the left operand after the
956*700637cbSDimitry Andric       // assignment...'.
957*700637cbSDimitry Andric       if (lhs.isBitField()) {
958*700637cbSDimitry Andric         rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);
959*700637cbSDimitry Andric       } else {
960*700637cbSDimitry Andric         cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
961*700637cbSDimitry Andric         CIRGenFunction::SourceLocRAIIObject loc{
962*700637cbSDimitry Andric             cgf, cgf.getLoc(e->getSourceRange())};
963*700637cbSDimitry Andric         cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);
964*700637cbSDimitry Andric       }
965*700637cbSDimitry Andric     }
966*700637cbSDimitry Andric 
967*700637cbSDimitry Andric     // If the result is clearly ignored, return now.
968*700637cbSDimitry Andric     if (ignore)
969*700637cbSDimitry Andric       return nullptr;
970*700637cbSDimitry Andric 
971*700637cbSDimitry Andric     // The result of an assignment in C is the assigned r-value.
972*700637cbSDimitry Andric     if (!cgf.getLangOpts().CPlusPlus)
973*700637cbSDimitry Andric       return rhs;
974*700637cbSDimitry Andric 
975*700637cbSDimitry Andric     // If the lvalue is non-volatile, return the computed value of the
976*700637cbSDimitry Andric     // assignment.
977*700637cbSDimitry Andric     if (!lhs.isVolatile())
978*700637cbSDimitry Andric       return rhs;
979*700637cbSDimitry Andric 
980*700637cbSDimitry Andric     // Otherwise, reload the value.
981*700637cbSDimitry Andric     return emitLoadOfLValue(lhs, e->getExprLoc());
982*700637cbSDimitry Andric   }
983*700637cbSDimitry Andric 
VisitBinComma(const BinaryOperator * e)984*700637cbSDimitry Andric   mlir::Value VisitBinComma(const BinaryOperator *e) {
985*700637cbSDimitry Andric     cgf.emitIgnoredExpr(e->getLHS());
986*700637cbSDimitry Andric     // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.
987*700637cbSDimitry Andric     return Visit(e->getRHS());
988*700637cbSDimitry Andric   }
989*700637cbSDimitry Andric 
VisitBinLAnd(const clang::BinaryOperator * e)990*700637cbSDimitry Andric   mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {
991*700637cbSDimitry Andric     if (e->getType()->isVectorType()) {
992*700637cbSDimitry Andric       assert(!cir::MissingFeatures::vectorType());
993*700637cbSDimitry Andric       return {};
994*700637cbSDimitry Andric     }
995*700637cbSDimitry Andric 
996*700637cbSDimitry Andric     assert(!cir::MissingFeatures::instrumentation());
997*700637cbSDimitry Andric     mlir::Type resTy = cgf.convertType(e->getType());
998*700637cbSDimitry Andric     mlir::Location loc = cgf.getLoc(e->getExprLoc());
999*700637cbSDimitry Andric 
1000*700637cbSDimitry Andric     CIRGenFunction::ConditionalEvaluation eval(cgf);
1001*700637cbSDimitry Andric 
1002*700637cbSDimitry Andric     mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1003*700637cbSDimitry Andric     auto resOp = builder.create<cir::TernaryOp>(
1004*700637cbSDimitry Andric         loc, lhsCondV, /*trueBuilder=*/
1005*700637cbSDimitry Andric         [&](mlir::OpBuilder &b, mlir::Location loc) {
1006*700637cbSDimitry Andric           CIRGenFunction::LexicalScope lexScope{cgf, loc,
1007*700637cbSDimitry Andric                                                 b.getInsertionBlock()};
1008*700637cbSDimitry Andric           cgf.curLexScope->setAsTernary();
1009*700637cbSDimitry Andric           b.create<cir::YieldOp>(loc, cgf.evaluateExprAsBool(e->getRHS()));
1010*700637cbSDimitry Andric         },
1011*700637cbSDimitry Andric         /*falseBuilder*/
1012*700637cbSDimitry Andric         [&](mlir::OpBuilder &b, mlir::Location loc) {
1013*700637cbSDimitry Andric           CIRGenFunction::LexicalScope lexScope{cgf, loc,
1014*700637cbSDimitry Andric                                                 b.getInsertionBlock()};
1015*700637cbSDimitry Andric           cgf.curLexScope->setAsTernary();
1016*700637cbSDimitry Andric           auto res = b.create<cir::ConstantOp>(loc, builder.getFalseAttr());
1017*700637cbSDimitry Andric           b.create<cir::YieldOp>(loc, res.getRes());
1018*700637cbSDimitry Andric         });
1019*700637cbSDimitry Andric     return maybePromoteBoolResult(resOp.getResult(), resTy);
1020*700637cbSDimitry Andric   }
1021*700637cbSDimitry Andric 
VisitBinLOr(const clang::BinaryOperator * e)1022*700637cbSDimitry Andric   mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {
1023*700637cbSDimitry Andric     if (e->getType()->isVectorType()) {
1024*700637cbSDimitry Andric       assert(!cir::MissingFeatures::vectorType());
1025*700637cbSDimitry Andric       return {};
1026*700637cbSDimitry Andric     }
1027*700637cbSDimitry Andric 
1028*700637cbSDimitry Andric     assert(!cir::MissingFeatures::instrumentation());
1029*700637cbSDimitry Andric     mlir::Type resTy = cgf.convertType(e->getType());
1030*700637cbSDimitry Andric     mlir::Location loc = cgf.getLoc(e->getExprLoc());
1031*700637cbSDimitry Andric 
1032*700637cbSDimitry Andric     CIRGenFunction::ConditionalEvaluation eval(cgf);
1033*700637cbSDimitry Andric 
1034*700637cbSDimitry Andric     mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1035*700637cbSDimitry Andric     auto resOp = builder.create<cir::TernaryOp>(
1036*700637cbSDimitry Andric         loc, lhsCondV, /*trueBuilder=*/
1037*700637cbSDimitry Andric         [&](mlir::OpBuilder &b, mlir::Location loc) {
1038*700637cbSDimitry Andric           CIRGenFunction::LexicalScope lexScope{cgf, loc,
1039*700637cbSDimitry Andric                                                 b.getInsertionBlock()};
1040*700637cbSDimitry Andric           cgf.curLexScope->setAsTernary();
1041*700637cbSDimitry Andric           auto res = b.create<cir::ConstantOp>(loc, builder.getTrueAttr());
1042*700637cbSDimitry Andric           b.create<cir::YieldOp>(loc, res.getRes());
1043*700637cbSDimitry Andric         },
1044*700637cbSDimitry Andric         /*falseBuilder*/
1045*700637cbSDimitry Andric         [&](mlir::OpBuilder &b, mlir::Location loc) {
1046*700637cbSDimitry Andric           CIRGenFunction::LexicalScope lexScope{cgf, loc,
1047*700637cbSDimitry Andric                                                 b.getInsertionBlock()};
1048*700637cbSDimitry Andric           cgf.curLexScope->setAsTernary();
1049*700637cbSDimitry Andric           b.create<cir::YieldOp>(loc, cgf.evaluateExprAsBool(e->getRHS()));
1050*700637cbSDimitry Andric         });
1051*700637cbSDimitry Andric 
1052*700637cbSDimitry Andric     return maybePromoteBoolResult(resOp.getResult(), resTy);
1053*700637cbSDimitry Andric   }
1054*700637cbSDimitry Andric };
1055*700637cbSDimitry Andric 
emitCompoundAssignLValue(const CompoundAssignOperator * e,mlir::Value (ScalarExprEmitter::* func)(const BinOpInfo &),mlir::Value & result)1056*700637cbSDimitry Andric LValue ScalarExprEmitter::emitCompoundAssignLValue(
1057*700637cbSDimitry Andric     const CompoundAssignOperator *e,
1058*700637cbSDimitry Andric     mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
1059*700637cbSDimitry Andric     mlir::Value &result) {
1060*700637cbSDimitry Andric   QualType lhsTy = e->getLHS()->getType();
1061*700637cbSDimitry Andric   BinOpInfo opInfo;
1062*700637cbSDimitry Andric 
1063*700637cbSDimitry Andric   if (e->getComputationResultType()->isAnyComplexType()) {
1064*700637cbSDimitry Andric     cgf.cgm.errorNYI(result.getLoc(), "complex lvalue assign");
1065*700637cbSDimitry Andric     return LValue();
1066*700637cbSDimitry Andric   }
1067*700637cbSDimitry Andric 
1068*700637cbSDimitry Andric   // Emit the RHS first.  __block variables need to have the rhs evaluated
1069*700637cbSDimitry Andric   // first, plus this should improve codegen a little.
1070*700637cbSDimitry Andric 
1071*700637cbSDimitry Andric   QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
1072*700637cbSDimitry Andric   if (promotionTypeCR.isNull())
1073*700637cbSDimitry Andric     promotionTypeCR = e->getComputationResultType();
1074*700637cbSDimitry Andric 
1075*700637cbSDimitry Andric   QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
1076*700637cbSDimitry Andric   QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
1077*700637cbSDimitry Andric 
1078*700637cbSDimitry Andric   if (!promotionTypeRHS.isNull())
1079*700637cbSDimitry Andric     opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
1080*700637cbSDimitry Andric   else
1081*700637cbSDimitry Andric     opInfo.rhs = Visit(e->getRHS());
1082*700637cbSDimitry Andric 
1083*700637cbSDimitry Andric   opInfo.fullType = promotionTypeCR;
1084*700637cbSDimitry Andric   opInfo.compType = opInfo.fullType;
1085*700637cbSDimitry Andric   if (const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1086*700637cbSDimitry Andric     opInfo.compType = vecType->getElementType();
1087*700637cbSDimitry Andric   opInfo.opcode = e->getOpcode();
1088*700637cbSDimitry Andric   opInfo.fpfeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1089*700637cbSDimitry Andric   opInfo.e = e;
1090*700637cbSDimitry Andric   opInfo.loc = e->getSourceRange();
1091*700637cbSDimitry Andric 
1092*700637cbSDimitry Andric   // Load/convert the LHS
1093*700637cbSDimitry Andric   LValue lhsLV = cgf.emitLValue(e->getLHS());
1094*700637cbSDimitry Andric 
1095*700637cbSDimitry Andric   if (lhsTy->getAs<AtomicType>()) {
1096*700637cbSDimitry Andric     cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
1097*700637cbSDimitry Andric     return LValue();
1098*700637cbSDimitry Andric   }
1099*700637cbSDimitry Andric 
1100*700637cbSDimitry Andric   opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
1101*700637cbSDimitry Andric 
1102*700637cbSDimitry Andric   CIRGenFunction::SourceLocRAIIObject sourceloc{
1103*700637cbSDimitry Andric       cgf, cgf.getLoc(e->getSourceRange())};
1104*700637cbSDimitry Andric   SourceLocation loc = e->getExprLoc();
1105*700637cbSDimitry Andric   if (!promotionTypeLHS.isNull())
1106*700637cbSDimitry Andric     opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1107*700637cbSDimitry Andric   else
1108*700637cbSDimitry Andric     opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1109*700637cbSDimitry Andric                                       e->getComputationLHSType(), loc);
1110*700637cbSDimitry Andric 
1111*700637cbSDimitry Andric   // Expand the binary operator.
1112*700637cbSDimitry Andric   result = (this->*func)(opInfo);
1113*700637cbSDimitry Andric 
1114*700637cbSDimitry Andric   // Convert the result back to the LHS type,
1115*700637cbSDimitry Andric   // potentially with Implicit Conversion sanitizer check.
1116*700637cbSDimitry Andric   result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1117*700637cbSDimitry Andric                                 ScalarConversionOpts(cgf.sanOpts));
1118*700637cbSDimitry Andric 
1119*700637cbSDimitry Andric   // Store the result value into the LHS lvalue. Bit-fields are handled
1120*700637cbSDimitry Andric   // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
1121*700637cbSDimitry Andric   // 'An assignment expression has the value of the left operand after the
1122*700637cbSDimitry Andric   // assignment...'.
1123*700637cbSDimitry Andric   if (lhsLV.isBitField())
1124*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "store through bitfield lvalue");
1125*700637cbSDimitry Andric   else
1126*700637cbSDimitry Andric     cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
1127*700637cbSDimitry Andric 
1128*700637cbSDimitry Andric   if (cgf.getLangOpts().OpenMP)
1129*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
1130*700637cbSDimitry Andric 
1131*700637cbSDimitry Andric   return lhsLV;
1132*700637cbSDimitry Andric }
1133*700637cbSDimitry Andric 
emitPromoted(const Expr * e,QualType promotionType)1134*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
1135*700637cbSDimitry Andric                                             QualType promotionType) {
1136*700637cbSDimitry Andric   e = e->IgnoreParens();
1137*700637cbSDimitry Andric   if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
1138*700637cbSDimitry Andric     switch (bo->getOpcode()) {
1139*700637cbSDimitry Andric #define HANDLE_BINOP(OP)                                                       \
1140*700637cbSDimitry Andric   case BO_##OP:                                                                \
1141*700637cbSDimitry Andric     return emit##OP(emitBinOps(bo, promotionType));
1142*700637cbSDimitry Andric       HANDLE_BINOP(Add)
1143*700637cbSDimitry Andric       HANDLE_BINOP(Sub)
1144*700637cbSDimitry Andric       HANDLE_BINOP(Mul)
1145*700637cbSDimitry Andric       HANDLE_BINOP(Div)
1146*700637cbSDimitry Andric #undef HANDLE_BINOP
1147*700637cbSDimitry Andric     default:
1148*700637cbSDimitry Andric       break;
1149*700637cbSDimitry Andric     }
1150*700637cbSDimitry Andric   } else if (isa<UnaryOperator>(e)) {
1151*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "unary operators");
1152*700637cbSDimitry Andric     return {};
1153*700637cbSDimitry Andric   }
1154*700637cbSDimitry Andric   mlir::Value result = Visit(const_cast<Expr *>(e));
1155*700637cbSDimitry Andric   if (result) {
1156*700637cbSDimitry Andric     if (!promotionType.isNull())
1157*700637cbSDimitry Andric       return emitPromotedValue(result, promotionType);
1158*700637cbSDimitry Andric     return emitUnPromotedValue(result, e->getType());
1159*700637cbSDimitry Andric   }
1160*700637cbSDimitry Andric   return result;
1161*700637cbSDimitry Andric }
1162*700637cbSDimitry Andric 
emitCompoundAssign(const CompoundAssignOperator * e,mlir::Value (ScalarExprEmitter::* func)(const BinOpInfo &))1163*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitCompoundAssign(
1164*700637cbSDimitry Andric     const CompoundAssignOperator *e,
1165*700637cbSDimitry Andric     mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
1166*700637cbSDimitry Andric 
1167*700637cbSDimitry Andric   bool ignore = std::exchange(ignoreResultAssign, false);
1168*700637cbSDimitry Andric   mlir::Value rhs;
1169*700637cbSDimitry Andric   LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1170*700637cbSDimitry Andric 
1171*700637cbSDimitry Andric   // If the result is clearly ignored, return now.
1172*700637cbSDimitry Andric   if (ignore)
1173*700637cbSDimitry Andric     return {};
1174*700637cbSDimitry Andric 
1175*700637cbSDimitry Andric   // The result of an assignment in C is the assigned r-value.
1176*700637cbSDimitry Andric   if (!cgf.getLangOpts().CPlusPlus)
1177*700637cbSDimitry Andric     return rhs;
1178*700637cbSDimitry Andric 
1179*700637cbSDimitry Andric   // If the lvalue is non-volatile, return the computed value of the assignment.
1180*700637cbSDimitry Andric   if (!lhs.isVolatile())
1181*700637cbSDimitry Andric     return rhs;
1182*700637cbSDimitry Andric 
1183*700637cbSDimitry Andric   // Otherwise, reload the value.
1184*700637cbSDimitry Andric   return emitLoadOfLValue(lhs, e->getExprLoc());
1185*700637cbSDimitry Andric }
1186*700637cbSDimitry Andric 
1187*700637cbSDimitry Andric } // namespace
1188*700637cbSDimitry Andric 
1189*700637cbSDimitry Andric LValue
emitCompoundAssignmentLValue(const CompoundAssignOperator * e)1190*700637cbSDimitry Andric CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
1191*700637cbSDimitry Andric   ScalarExprEmitter emitter(*this, builder);
1192*700637cbSDimitry Andric   mlir::Value result;
1193*700637cbSDimitry Andric   switch (e->getOpcode()) {
1194*700637cbSDimitry Andric #define COMPOUND_OP(Op)                                                        \
1195*700637cbSDimitry Andric   case BO_##Op##Assign:                                                        \
1196*700637cbSDimitry Andric     return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op,   \
1197*700637cbSDimitry Andric                                             result)
1198*700637cbSDimitry Andric     COMPOUND_OP(Mul);
1199*700637cbSDimitry Andric     COMPOUND_OP(Div);
1200*700637cbSDimitry Andric     COMPOUND_OP(Rem);
1201*700637cbSDimitry Andric     COMPOUND_OP(Add);
1202*700637cbSDimitry Andric     COMPOUND_OP(Sub);
1203*700637cbSDimitry Andric     COMPOUND_OP(Shl);
1204*700637cbSDimitry Andric     COMPOUND_OP(Shr);
1205*700637cbSDimitry Andric     COMPOUND_OP(And);
1206*700637cbSDimitry Andric     COMPOUND_OP(Xor);
1207*700637cbSDimitry Andric     COMPOUND_OP(Or);
1208*700637cbSDimitry Andric #undef COMPOUND_OP
1209*700637cbSDimitry Andric 
1210*700637cbSDimitry Andric   case BO_PtrMemD:
1211*700637cbSDimitry Andric   case BO_PtrMemI:
1212*700637cbSDimitry Andric   case BO_Mul:
1213*700637cbSDimitry Andric   case BO_Div:
1214*700637cbSDimitry Andric   case BO_Rem:
1215*700637cbSDimitry Andric   case BO_Add:
1216*700637cbSDimitry Andric   case BO_Sub:
1217*700637cbSDimitry Andric   case BO_Shl:
1218*700637cbSDimitry Andric   case BO_Shr:
1219*700637cbSDimitry Andric   case BO_LT:
1220*700637cbSDimitry Andric   case BO_GT:
1221*700637cbSDimitry Andric   case BO_LE:
1222*700637cbSDimitry Andric   case BO_GE:
1223*700637cbSDimitry Andric   case BO_EQ:
1224*700637cbSDimitry Andric   case BO_NE:
1225*700637cbSDimitry Andric   case BO_Cmp:
1226*700637cbSDimitry Andric   case BO_And:
1227*700637cbSDimitry Andric   case BO_Xor:
1228*700637cbSDimitry Andric   case BO_Or:
1229*700637cbSDimitry Andric   case BO_LAnd:
1230*700637cbSDimitry Andric   case BO_LOr:
1231*700637cbSDimitry Andric   case BO_Assign:
1232*700637cbSDimitry Andric   case BO_Comma:
1233*700637cbSDimitry Andric     llvm_unreachable("Not valid compound assignment operators");
1234*700637cbSDimitry Andric   }
1235*700637cbSDimitry Andric   llvm_unreachable("Unhandled compound assignment operator");
1236*700637cbSDimitry Andric }
1237*700637cbSDimitry Andric 
1238*700637cbSDimitry Andric /// Emit the computation of the specified expression of scalar type.
emitScalarExpr(const Expr * e)1239*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
1240*700637cbSDimitry Andric   assert(e && hasScalarEvaluationKind(e->getType()) &&
1241*700637cbSDimitry Andric          "Invalid scalar expression to emit");
1242*700637cbSDimitry Andric 
1243*700637cbSDimitry Andric   return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1244*700637cbSDimitry Andric }
1245*700637cbSDimitry Andric 
emitPromotedScalarExpr(const Expr * e,QualType promotionType)1246*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e,
1247*700637cbSDimitry Andric                                                    QualType promotionType) {
1248*700637cbSDimitry Andric   if (!promotionType.isNull())
1249*700637cbSDimitry Andric     return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);
1250*700637cbSDimitry Andric   return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1251*700637cbSDimitry Andric }
1252*700637cbSDimitry Andric 
mustVisitNullValue(const Expr * e)1253*700637cbSDimitry Andric [[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {
1254*700637cbSDimitry Andric   // If a null pointer expression's type is the C++0x nullptr_t and
1255*700637cbSDimitry Andric   // the expression is not a simple literal, it must be evaluated
1256*700637cbSDimitry Andric   // for its potential side effects.
1257*700637cbSDimitry Andric   if (isa<IntegerLiteral>(e) || isa<CXXNullPtrLiteralExpr>(e))
1258*700637cbSDimitry Andric     return false;
1259*700637cbSDimitry Andric   return e->getType()->isNullPtrType();
1260*700637cbSDimitry Andric }
1261*700637cbSDimitry Andric 
1262*700637cbSDimitry Andric /// If \p e is a widened promoted integer, get its base (unpromoted) type.
1263*700637cbSDimitry Andric static std::optional<QualType>
getUnwidenedIntegerType(const ASTContext & astContext,const Expr * e)1264*700637cbSDimitry Andric getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {
1265*700637cbSDimitry Andric   const Expr *base = e->IgnoreImpCasts();
1266*700637cbSDimitry Andric   if (e == base)
1267*700637cbSDimitry Andric     return std::nullopt;
1268*700637cbSDimitry Andric 
1269*700637cbSDimitry Andric   QualType baseTy = base->getType();
1270*700637cbSDimitry Andric   if (!astContext.isPromotableIntegerType(baseTy) ||
1271*700637cbSDimitry Andric       astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))
1272*700637cbSDimitry Andric     return std::nullopt;
1273*700637cbSDimitry Andric 
1274*700637cbSDimitry Andric   return baseTy;
1275*700637cbSDimitry Andric }
1276*700637cbSDimitry Andric 
1277*700637cbSDimitry Andric /// Check if \p e is a widened promoted integer.
isWidenedIntegerOp(const ASTContext & astContext,const Expr * e)1278*700637cbSDimitry Andric [[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,
1279*700637cbSDimitry Andric                                                 const Expr *e) {
1280*700637cbSDimitry Andric   return getUnwidenedIntegerType(astContext, e).has_value();
1281*700637cbSDimitry Andric }
1282*700637cbSDimitry Andric 
1283*700637cbSDimitry Andric /// Check if we can skip the overflow check for \p Op.
canElideOverflowCheck(const ASTContext & astContext,const BinOpInfo & op)1284*700637cbSDimitry Andric [[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,
1285*700637cbSDimitry Andric                                                    const BinOpInfo &op) {
1286*700637cbSDimitry Andric   assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1287*700637cbSDimitry Andric          "Expected a unary or binary operator");
1288*700637cbSDimitry Andric 
1289*700637cbSDimitry Andric   // If the binop has constant inputs and we can prove there is no overflow,
1290*700637cbSDimitry Andric   // we can elide the overflow check.
1291*700637cbSDimitry Andric   if (!op.mayHaveIntegerOverflow())
1292*700637cbSDimitry Andric     return true;
1293*700637cbSDimitry Andric 
1294*700637cbSDimitry Andric   // If a unary op has a widened operand, the op cannot overflow.
1295*700637cbSDimitry Andric   if (const auto *uo = dyn_cast<UnaryOperator>(op.e))
1296*700637cbSDimitry Andric     return !uo->canOverflow();
1297*700637cbSDimitry Andric 
1298*700637cbSDimitry Andric   // We usually don't need overflow checks for binops with widened operands.
1299*700637cbSDimitry Andric   // Multiplication with promoted unsigned operands is a special case.
1300*700637cbSDimitry Andric   const auto *bo = cast<BinaryOperator>(op.e);
1301*700637cbSDimitry Andric   std::optional<QualType> optionalLHSTy =
1302*700637cbSDimitry Andric       getUnwidenedIntegerType(astContext, bo->getLHS());
1303*700637cbSDimitry Andric   if (!optionalLHSTy)
1304*700637cbSDimitry Andric     return false;
1305*700637cbSDimitry Andric 
1306*700637cbSDimitry Andric   std::optional<QualType> optionalRHSTy =
1307*700637cbSDimitry Andric       getUnwidenedIntegerType(astContext, bo->getRHS());
1308*700637cbSDimitry Andric   if (!optionalRHSTy)
1309*700637cbSDimitry Andric     return false;
1310*700637cbSDimitry Andric 
1311*700637cbSDimitry Andric   QualType lhsTy = *optionalLHSTy;
1312*700637cbSDimitry Andric   QualType rhsTy = *optionalRHSTy;
1313*700637cbSDimitry Andric 
1314*700637cbSDimitry Andric   // This is the simple case: binops without unsigned multiplication, and with
1315*700637cbSDimitry Andric   // widened operands. No overflow check is needed here.
1316*700637cbSDimitry Andric   if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1317*700637cbSDimitry Andric       !lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())
1318*700637cbSDimitry Andric     return true;
1319*700637cbSDimitry Andric 
1320*700637cbSDimitry Andric   // For unsigned multiplication the overflow check can be elided if either one
1321*700637cbSDimitry Andric   // of the unpromoted types are less than half the size of the promoted type.
1322*700637cbSDimitry Andric   unsigned promotedSize = astContext.getTypeSize(op.e->getType());
1323*700637cbSDimitry Andric   return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||
1324*700637cbSDimitry Andric          (2 * astContext.getTypeSize(rhsTy)) < promotedSize;
1325*700637cbSDimitry Andric }
1326*700637cbSDimitry Andric 
1327*700637cbSDimitry Andric /// Emit pointer + index arithmetic.
emitPointerArithmetic(CIRGenFunction & cgf,const BinOpInfo & op,bool isSubtraction)1328*700637cbSDimitry Andric static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf,
1329*700637cbSDimitry Andric                                          const BinOpInfo &op,
1330*700637cbSDimitry Andric                                          bool isSubtraction) {
1331*700637cbSDimitry Andric   // Must have binary (not unary) expr here.  Unary pointer
1332*700637cbSDimitry Andric   // increment/decrement doesn't use this path.
1333*700637cbSDimitry Andric   const BinaryOperator *expr = cast<BinaryOperator>(op.e);
1334*700637cbSDimitry Andric 
1335*700637cbSDimitry Andric   mlir::Value pointer = op.lhs;
1336*700637cbSDimitry Andric   Expr *pointerOperand = expr->getLHS();
1337*700637cbSDimitry Andric   mlir::Value index = op.rhs;
1338*700637cbSDimitry Andric   Expr *indexOperand = expr->getRHS();
1339*700637cbSDimitry Andric 
1340*700637cbSDimitry Andric   // In the case of subtraction, the FE has ensured that the LHS is always the
1341*700637cbSDimitry Andric   // pointer. However, addition can have the pointer on either side. We will
1342*700637cbSDimitry Andric   // always have a pointer operand and an integer operand, so if the LHS wasn't
1343*700637cbSDimitry Andric   // a pointer, we need to swap our values.
1344*700637cbSDimitry Andric   if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1345*700637cbSDimitry Andric     std::swap(pointer, index);
1346*700637cbSDimitry Andric     std::swap(pointerOperand, indexOperand);
1347*700637cbSDimitry Andric   }
1348*700637cbSDimitry Andric   assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1349*700637cbSDimitry Andric          "Need a pointer operand");
1350*700637cbSDimitry Andric   assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");
1351*700637cbSDimitry Andric 
1352*700637cbSDimitry Andric   // Some versions of glibc and gcc use idioms (particularly in their malloc
1353*700637cbSDimitry Andric   // routines) that add a pointer-sized integer (known to be a pointer value)
1354*700637cbSDimitry Andric   // to a null pointer in order to cast the value back to an integer or as
1355*700637cbSDimitry Andric   // part of a pointer alignment algorithm.  This is undefined behavior, but
1356*700637cbSDimitry Andric   // we'd like to be able to compile programs that use it.
1357*700637cbSDimitry Andric   //
1358*700637cbSDimitry Andric   // Normally, we'd generate a GEP with a null-pointer base here in response
1359*700637cbSDimitry Andric   // to that code, but it's also UB to dereference a pointer created that
1360*700637cbSDimitry Andric   // way.  Instead (as an acknowledged hack to tolerate the idiom) we will
1361*700637cbSDimitry Andric   // generate a direct cast of the integer value to a pointer.
1362*700637cbSDimitry Andric   //
1363*700637cbSDimitry Andric   // The idiom (p = nullptr + N) is not met if any of the following are true:
1364*700637cbSDimitry Andric   //
1365*700637cbSDimitry Andric   //   The operation is subtraction.
1366*700637cbSDimitry Andric   //   The index is not pointer-sized.
1367*700637cbSDimitry Andric   //   The pointer type is not byte-sized.
1368*700637cbSDimitry Andric   //
1369*700637cbSDimitry Andric   if (BinaryOperator::isNullPointerArithmeticExtension(
1370*700637cbSDimitry Andric           cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))
1371*700637cbSDimitry Andric     return cgf.getBuilder().createIntToPtr(index, pointer.getType());
1372*700637cbSDimitry Andric 
1373*700637cbSDimitry Andric   // Differently from LLVM codegen, ABI bits for index sizes is handled during
1374*700637cbSDimitry Andric   // LLVM lowering.
1375*700637cbSDimitry Andric 
1376*700637cbSDimitry Andric   // If this is subtraction, negate the index.
1377*700637cbSDimitry Andric   if (isSubtraction)
1378*700637cbSDimitry Andric     index = cgf.getBuilder().createNeg(index);
1379*700637cbSDimitry Andric 
1380*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
1381*700637cbSDimitry Andric 
1382*700637cbSDimitry Andric   const PointerType *pointerType =
1383*700637cbSDimitry Andric       pointerOperand->getType()->getAs<PointerType>();
1384*700637cbSDimitry Andric   if (!pointerType) {
1385*700637cbSDimitry Andric     cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");
1386*700637cbSDimitry Andric     return nullptr;
1387*700637cbSDimitry Andric   }
1388*700637cbSDimitry Andric 
1389*700637cbSDimitry Andric   QualType elementType = pointerType->getPointeeType();
1390*700637cbSDimitry Andric   if (cgf.getContext().getAsVariableArrayType(elementType)) {
1391*700637cbSDimitry Andric     cgf.cgm.errorNYI("variable array type");
1392*700637cbSDimitry Andric     return nullptr;
1393*700637cbSDimitry Andric   }
1394*700637cbSDimitry Andric 
1395*700637cbSDimitry Andric   if (elementType->isVoidType() || elementType->isFunctionType()) {
1396*700637cbSDimitry Andric     cgf.cgm.errorNYI("void* or function pointer arithmetic");
1397*700637cbSDimitry Andric     return nullptr;
1398*700637cbSDimitry Andric   }
1399*700637cbSDimitry Andric 
1400*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
1401*700637cbSDimitry Andric   return cgf.getBuilder().create<cir::PtrStrideOp>(
1402*700637cbSDimitry Andric       cgf.getLoc(op.e->getExprLoc()), pointer.getType(), pointer, index);
1403*700637cbSDimitry Andric }
1404*700637cbSDimitry Andric 
emitMul(const BinOpInfo & ops)1405*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {
1406*700637cbSDimitry Andric   const mlir::Location loc = cgf.getLoc(ops.loc);
1407*700637cbSDimitry Andric   if (ops.compType->isSignedIntegerOrEnumerationType()) {
1408*700637cbSDimitry Andric     switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1409*700637cbSDimitry Andric     case LangOptions::SOB_Defined:
1410*700637cbSDimitry Andric       if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1411*700637cbSDimitry Andric         return builder.createMul(loc, ops.lhs, ops.rhs);
1412*700637cbSDimitry Andric       [[fallthrough]];
1413*700637cbSDimitry Andric     case LangOptions::SOB_Undefined:
1414*700637cbSDimitry Andric       if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1415*700637cbSDimitry Andric         return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1416*700637cbSDimitry Andric       [[fallthrough]];
1417*700637cbSDimitry Andric     case LangOptions::SOB_Trapping:
1418*700637cbSDimitry Andric       if (canElideOverflowCheck(cgf.getContext(), ops))
1419*700637cbSDimitry Andric         return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1420*700637cbSDimitry Andric       cgf.cgm.errorNYI("sanitizers");
1421*700637cbSDimitry Andric     }
1422*700637cbSDimitry Andric   }
1423*700637cbSDimitry Andric   if (ops.fullType->isConstantMatrixType()) {
1424*700637cbSDimitry Andric     assert(!cir::MissingFeatures::matrixType());
1425*700637cbSDimitry Andric     cgf.cgm.errorNYI("matrix types");
1426*700637cbSDimitry Andric     return nullptr;
1427*700637cbSDimitry Andric   }
1428*700637cbSDimitry Andric   if (ops.compType->isUnsignedIntegerType() &&
1429*700637cbSDimitry Andric       cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1430*700637cbSDimitry Andric       !canElideOverflowCheck(cgf.getContext(), ops))
1431*700637cbSDimitry Andric     cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1432*700637cbSDimitry Andric 
1433*700637cbSDimitry Andric   if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1434*700637cbSDimitry Andric     assert(!cir::MissingFeatures::cgFPOptionsRAII());
1435*700637cbSDimitry Andric     return builder.createFMul(loc, ops.lhs, ops.rhs);
1436*700637cbSDimitry Andric   }
1437*700637cbSDimitry Andric 
1438*700637cbSDimitry Andric   if (ops.isFixedPointOp()) {
1439*700637cbSDimitry Andric     assert(!cir::MissingFeatures::fixedPointType());
1440*700637cbSDimitry Andric     cgf.cgm.errorNYI("fixed point");
1441*700637cbSDimitry Andric     return nullptr;
1442*700637cbSDimitry Andric   }
1443*700637cbSDimitry Andric 
1444*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1445*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1446*700637cbSDimitry Andric                                     cir::BinOpKind::Mul, ops.lhs, ops.rhs);
1447*700637cbSDimitry Andric }
emitDiv(const BinOpInfo & ops)1448*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
1449*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1450*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1451*700637cbSDimitry Andric                                     cir::BinOpKind::Div, ops.lhs, ops.rhs);
1452*700637cbSDimitry Andric }
emitRem(const BinOpInfo & ops)1453*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
1454*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1455*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1456*700637cbSDimitry Andric                                     cir::BinOpKind::Rem, ops.lhs, ops.rhs);
1457*700637cbSDimitry Andric }
1458*700637cbSDimitry Andric 
emitAdd(const BinOpInfo & ops)1459*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
1460*700637cbSDimitry Andric   if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1461*700637cbSDimitry Andric       mlir::isa<cir::PointerType>(ops.rhs.getType()))
1462*700637cbSDimitry Andric     return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/false);
1463*700637cbSDimitry Andric 
1464*700637cbSDimitry Andric   const mlir::Location loc = cgf.getLoc(ops.loc);
1465*700637cbSDimitry Andric   if (ops.compType->isSignedIntegerOrEnumerationType()) {
1466*700637cbSDimitry Andric     switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1467*700637cbSDimitry Andric     case LangOptions::SOB_Defined:
1468*700637cbSDimitry Andric       if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1469*700637cbSDimitry Andric         return builder.createAdd(loc, ops.lhs, ops.rhs);
1470*700637cbSDimitry Andric       [[fallthrough]];
1471*700637cbSDimitry Andric     case LangOptions::SOB_Undefined:
1472*700637cbSDimitry Andric       if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1473*700637cbSDimitry Andric         return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1474*700637cbSDimitry Andric       [[fallthrough]];
1475*700637cbSDimitry Andric     case LangOptions::SOB_Trapping:
1476*700637cbSDimitry Andric       if (canElideOverflowCheck(cgf.getContext(), ops))
1477*700637cbSDimitry Andric         return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1478*700637cbSDimitry Andric       cgf.cgm.errorNYI("sanitizers");
1479*700637cbSDimitry Andric     }
1480*700637cbSDimitry Andric   }
1481*700637cbSDimitry Andric   if (ops.fullType->isConstantMatrixType()) {
1482*700637cbSDimitry Andric     assert(!cir::MissingFeatures::matrixType());
1483*700637cbSDimitry Andric     cgf.cgm.errorNYI("matrix types");
1484*700637cbSDimitry Andric     return nullptr;
1485*700637cbSDimitry Andric   }
1486*700637cbSDimitry Andric 
1487*700637cbSDimitry Andric   if (ops.compType->isUnsignedIntegerType() &&
1488*700637cbSDimitry Andric       cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1489*700637cbSDimitry Andric       !canElideOverflowCheck(cgf.getContext(), ops))
1490*700637cbSDimitry Andric     cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1491*700637cbSDimitry Andric 
1492*700637cbSDimitry Andric   if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1493*700637cbSDimitry Andric     assert(!cir::MissingFeatures::cgFPOptionsRAII());
1494*700637cbSDimitry Andric     return builder.createFAdd(loc, ops.lhs, ops.rhs);
1495*700637cbSDimitry Andric   }
1496*700637cbSDimitry Andric 
1497*700637cbSDimitry Andric   if (ops.isFixedPointOp()) {
1498*700637cbSDimitry Andric     assert(!cir::MissingFeatures::fixedPointType());
1499*700637cbSDimitry Andric     cgf.cgm.errorNYI("fixed point");
1500*700637cbSDimitry Andric     return {};
1501*700637cbSDimitry Andric   }
1502*700637cbSDimitry Andric 
1503*700637cbSDimitry Andric   return builder.create<cir::BinOp>(loc, cgf.convertType(ops.fullType),
1504*700637cbSDimitry Andric                                     cir::BinOpKind::Add, ops.lhs, ops.rhs);
1505*700637cbSDimitry Andric }
1506*700637cbSDimitry Andric 
emitSub(const BinOpInfo & ops)1507*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
1508*700637cbSDimitry Andric   const mlir::Location loc = cgf.getLoc(ops.loc);
1509*700637cbSDimitry Andric   // The LHS is always a pointer if either side is.
1510*700637cbSDimitry Andric   if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1511*700637cbSDimitry Andric     if (ops.compType->isSignedIntegerOrEnumerationType()) {
1512*700637cbSDimitry Andric       switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1513*700637cbSDimitry Andric       case LangOptions::SOB_Defined: {
1514*700637cbSDimitry Andric         if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1515*700637cbSDimitry Andric           return builder.createSub(loc, ops.lhs, ops.rhs);
1516*700637cbSDimitry Andric         [[fallthrough]];
1517*700637cbSDimitry Andric       }
1518*700637cbSDimitry Andric       case LangOptions::SOB_Undefined:
1519*700637cbSDimitry Andric         if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1520*700637cbSDimitry Andric           return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1521*700637cbSDimitry Andric         [[fallthrough]];
1522*700637cbSDimitry Andric       case LangOptions::SOB_Trapping:
1523*700637cbSDimitry Andric         if (canElideOverflowCheck(cgf.getContext(), ops))
1524*700637cbSDimitry Andric           return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1525*700637cbSDimitry Andric         cgf.cgm.errorNYI("sanitizers");
1526*700637cbSDimitry Andric       }
1527*700637cbSDimitry Andric     }
1528*700637cbSDimitry Andric 
1529*700637cbSDimitry Andric     if (ops.fullType->isConstantMatrixType()) {
1530*700637cbSDimitry Andric       assert(!cir::MissingFeatures::matrixType());
1531*700637cbSDimitry Andric       cgf.cgm.errorNYI("matrix types");
1532*700637cbSDimitry Andric       return nullptr;
1533*700637cbSDimitry Andric     }
1534*700637cbSDimitry Andric 
1535*700637cbSDimitry Andric     if (ops.compType->isUnsignedIntegerType() &&
1536*700637cbSDimitry Andric         cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1537*700637cbSDimitry Andric         !canElideOverflowCheck(cgf.getContext(), ops))
1538*700637cbSDimitry Andric       cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1539*700637cbSDimitry Andric 
1540*700637cbSDimitry Andric     if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1541*700637cbSDimitry Andric       assert(!cir::MissingFeatures::cgFPOptionsRAII());
1542*700637cbSDimitry Andric       return builder.createFSub(loc, ops.lhs, ops.rhs);
1543*700637cbSDimitry Andric     }
1544*700637cbSDimitry Andric 
1545*700637cbSDimitry Andric     if (ops.isFixedPointOp()) {
1546*700637cbSDimitry Andric       assert(!cir::MissingFeatures::fixedPointType());
1547*700637cbSDimitry Andric       cgf.cgm.errorNYI("fixed point");
1548*700637cbSDimitry Andric       return {};
1549*700637cbSDimitry Andric     }
1550*700637cbSDimitry Andric 
1551*700637cbSDimitry Andric     return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1552*700637cbSDimitry Andric                                       cgf.convertType(ops.fullType),
1553*700637cbSDimitry Andric                                       cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1554*700637cbSDimitry Andric   }
1555*700637cbSDimitry Andric 
1556*700637cbSDimitry Andric   // If the RHS is not a pointer, then we have normal pointer
1557*700637cbSDimitry Andric   // arithmetic.
1558*700637cbSDimitry Andric   if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1559*700637cbSDimitry Andric     return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);
1560*700637cbSDimitry Andric 
1561*700637cbSDimitry Andric   // Otherwise, this is a pointer subtraction
1562*700637cbSDimitry Andric 
1563*700637cbSDimitry Andric   // Do the raw subtraction part.
1564*700637cbSDimitry Andric   //
1565*700637cbSDimitry Andric   // TODO(cir): note for LLVM lowering out of this; when expanding this into
1566*700637cbSDimitry Andric   // LLVM we shall take VLA's, division by element size, etc.
1567*700637cbSDimitry Andric   //
1568*700637cbSDimitry Andric   // See more in `EmitSub` in CGExprScalar.cpp.
1569*700637cbSDimitry Andric   assert(!cir::MissingFeatures::ptrDiffOp());
1570*700637cbSDimitry Andric   cgf.cgm.errorNYI("ptrdiff");
1571*700637cbSDimitry Andric   return {};
1572*700637cbSDimitry Andric }
1573*700637cbSDimitry Andric 
emitShl(const BinOpInfo & ops)1574*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
1575*700637cbSDimitry Andric   // TODO: This misses out on the sanitizer check below.
1576*700637cbSDimitry Andric   if (ops.isFixedPointOp()) {
1577*700637cbSDimitry Andric     assert(cir::MissingFeatures::fixedPointType());
1578*700637cbSDimitry Andric     cgf.cgm.errorNYI("fixed point");
1579*700637cbSDimitry Andric     return {};
1580*700637cbSDimitry Andric   }
1581*700637cbSDimitry Andric 
1582*700637cbSDimitry Andric   // CIR accepts shift between different types, meaning nothing special
1583*700637cbSDimitry Andric   // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
1584*700637cbSDimitry Andric   // promote or truncate the RHS to the same size as the LHS.
1585*700637cbSDimitry Andric 
1586*700637cbSDimitry Andric   bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&
1587*700637cbSDimitry Andric                             ops.compType->hasSignedIntegerRepresentation() &&
1588*700637cbSDimitry Andric                             !cgf.getLangOpts().isSignedOverflowDefined() &&
1589*700637cbSDimitry Andric                             !cgf.getLangOpts().CPlusPlus20;
1590*700637cbSDimitry Andric   bool sanitizeUnsignedBase =
1591*700637cbSDimitry Andric       cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&
1592*700637cbSDimitry Andric       ops.compType->hasUnsignedIntegerRepresentation();
1593*700637cbSDimitry Andric   bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1594*700637cbSDimitry Andric   bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);
1595*700637cbSDimitry Andric 
1596*700637cbSDimitry Andric   // OpenCL 6.3j: shift values are effectively % word size of LHS.
1597*700637cbSDimitry Andric   if (cgf.getLangOpts().OpenCL)
1598*700637cbSDimitry Andric     cgf.cgm.errorNYI("opencl");
1599*700637cbSDimitry Andric   else if ((sanitizeBase || sanitizeExponent) &&
1600*700637cbSDimitry Andric            mlir::isa<cir::IntType>(ops.lhs.getType()))
1601*700637cbSDimitry Andric     cgf.cgm.errorNYI("sanitizers");
1602*700637cbSDimitry Andric 
1603*700637cbSDimitry Andric   return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
1604*700637cbSDimitry Andric }
1605*700637cbSDimitry Andric 
emitShr(const BinOpInfo & ops)1606*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
1607*700637cbSDimitry Andric   // TODO: This misses out on the sanitizer check below.
1608*700637cbSDimitry Andric   if (ops.isFixedPointOp()) {
1609*700637cbSDimitry Andric     assert(cir::MissingFeatures::fixedPointType());
1610*700637cbSDimitry Andric     cgf.cgm.errorNYI("fixed point");
1611*700637cbSDimitry Andric     return {};
1612*700637cbSDimitry Andric   }
1613*700637cbSDimitry Andric 
1614*700637cbSDimitry Andric   // CIR accepts shift between different types, meaning nothing special
1615*700637cbSDimitry Andric   // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
1616*700637cbSDimitry Andric   // promote or truncate the RHS to the same size as the LHS.
1617*700637cbSDimitry Andric 
1618*700637cbSDimitry Andric   // OpenCL 6.3j: shift values are effectively % word size of LHS.
1619*700637cbSDimitry Andric   if (cgf.getLangOpts().OpenCL)
1620*700637cbSDimitry Andric     cgf.cgm.errorNYI("opencl");
1621*700637cbSDimitry Andric   else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&
1622*700637cbSDimitry Andric            mlir::isa<cir::IntType>(ops.lhs.getType()))
1623*700637cbSDimitry Andric     cgf.cgm.errorNYI("sanitizers");
1624*700637cbSDimitry Andric 
1625*700637cbSDimitry Andric   // Note that we don't need to distinguish unsigned treatment at this
1626*700637cbSDimitry Andric   // point since it will be handled later by LLVM lowering.
1627*700637cbSDimitry Andric   return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
1628*700637cbSDimitry Andric }
1629*700637cbSDimitry Andric 
emitAnd(const BinOpInfo & ops)1630*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {
1631*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1632*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1633*700637cbSDimitry Andric                                     cir::BinOpKind::And, ops.lhs, ops.rhs);
1634*700637cbSDimitry Andric }
emitXor(const BinOpInfo & ops)1635*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {
1636*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1637*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1638*700637cbSDimitry Andric                                     cir::BinOpKind::Xor, ops.lhs, ops.rhs);
1639*700637cbSDimitry Andric }
emitOr(const BinOpInfo & ops)1640*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {
1641*700637cbSDimitry Andric   return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1642*700637cbSDimitry Andric                                     cgf.convertType(ops.fullType),
1643*700637cbSDimitry Andric                                     cir::BinOpKind::Or, ops.lhs, ops.rhs);
1644*700637cbSDimitry Andric }
1645*700637cbSDimitry Andric 
1646*700637cbSDimitry Andric // Emit code for an explicit or implicit cast.  Implicit
1647*700637cbSDimitry Andric // casts have to handle a more broad range of conversions than explicit
1648*700637cbSDimitry Andric // casts, as they handle things like function to ptr-to-function decay
1649*700637cbSDimitry Andric // etc.
VisitCastExpr(CastExpr * ce)1650*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
1651*700637cbSDimitry Andric   Expr *subExpr = ce->getSubExpr();
1652*700637cbSDimitry Andric   QualType destTy = ce->getType();
1653*700637cbSDimitry Andric   CastKind kind = ce->getCastKind();
1654*700637cbSDimitry Andric 
1655*700637cbSDimitry Andric   // These cases are generally not written to ignore the result of evaluating
1656*700637cbSDimitry Andric   // their sub-expressions, so we clear this now.
1657*700637cbSDimitry Andric   ignoreResultAssign = false;
1658*700637cbSDimitry Andric 
1659*700637cbSDimitry Andric   switch (kind) {
1660*700637cbSDimitry Andric   case clang::CK_Dependent:
1661*700637cbSDimitry Andric     llvm_unreachable("dependent cast kind in CIR gen!");
1662*700637cbSDimitry Andric   case clang::CK_BuiltinFnToFnPtr:
1663*700637cbSDimitry Andric     llvm_unreachable("builtin functions are handled elsewhere");
1664*700637cbSDimitry Andric 
1665*700637cbSDimitry Andric   case CK_CPointerToObjCPointerCast:
1666*700637cbSDimitry Andric   case CK_BlockPointerToObjCPointerCast:
1667*700637cbSDimitry Andric   case CK_AnyPointerToBlockPointerCast:
1668*700637cbSDimitry Andric   case CK_BitCast: {
1669*700637cbSDimitry Andric     mlir::Value src = Visit(const_cast<Expr *>(subExpr));
1670*700637cbSDimitry Andric     mlir::Type dstTy = cgf.convertType(destTy);
1671*700637cbSDimitry Andric 
1672*700637cbSDimitry Andric     assert(!cir::MissingFeatures::addressSpace());
1673*700637cbSDimitry Andric 
1674*700637cbSDimitry Andric     if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
1675*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1676*700637cbSDimitry Andric                                      "sanitizer support");
1677*700637cbSDimitry Andric 
1678*700637cbSDimitry Andric     if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
1679*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1680*700637cbSDimitry Andric                                      "strict vtable pointers");
1681*700637cbSDimitry Andric 
1682*700637cbSDimitry Andric     // Update heapallocsite metadata when there is an explicit pointer cast.
1683*700637cbSDimitry Andric     assert(!cir::MissingFeatures::addHeapAllocSiteMetadata());
1684*700637cbSDimitry Andric 
1685*700637cbSDimitry Andric     // If Src is a fixed vector and Dst is a scalable vector, and both have the
1686*700637cbSDimitry Andric     // same element type, use the llvm.vector.insert intrinsic to perform the
1687*700637cbSDimitry Andric     // bitcast.
1688*700637cbSDimitry Andric     assert(!cir::MissingFeatures::scalableVectors());
1689*700637cbSDimitry Andric 
1690*700637cbSDimitry Andric     // If Src is a scalable vector and Dst is a fixed vector, and both have the
1691*700637cbSDimitry Andric     // same element type, use the llvm.vector.extract intrinsic to perform the
1692*700637cbSDimitry Andric     // bitcast.
1693*700637cbSDimitry Andric     assert(!cir::MissingFeatures::scalableVectors());
1694*700637cbSDimitry Andric 
1695*700637cbSDimitry Andric     // Perform VLAT <-> VLST bitcast through memory.
1696*700637cbSDimitry Andric     // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
1697*700637cbSDimitry Andric     //       require the element types of the vectors to be the same, we
1698*700637cbSDimitry Andric     //       need to keep this around for bitcasts between VLAT <-> VLST where
1699*700637cbSDimitry Andric     //       the element types of the vectors are not the same, until we figure
1700*700637cbSDimitry Andric     //       out a better way of doing these casts.
1701*700637cbSDimitry Andric     assert(!cir::MissingFeatures::scalableVectors());
1702*700637cbSDimitry Andric 
1703*700637cbSDimitry Andric     return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
1704*700637cbSDimitry Andric                                           src, dstTy);
1705*700637cbSDimitry Andric   }
1706*700637cbSDimitry Andric 
1707*700637cbSDimitry Andric   case CK_AtomicToNonAtomic: {
1708*700637cbSDimitry Andric     cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1709*700637cbSDimitry Andric                                    "CastExpr: ", ce->getCastKindName());
1710*700637cbSDimitry Andric     mlir::Location loc = cgf.getLoc(subExpr->getSourceRange());
1711*700637cbSDimitry Andric     return cgf.createDummyValue(loc, destTy);
1712*700637cbSDimitry Andric   }
1713*700637cbSDimitry Andric   case CK_NonAtomicToAtomic:
1714*700637cbSDimitry Andric   case CK_UserDefinedConversion:
1715*700637cbSDimitry Andric     return Visit(const_cast<Expr *>(subExpr));
1716*700637cbSDimitry Andric   case CK_NoOp: {
1717*700637cbSDimitry Andric     auto v = Visit(const_cast<Expr *>(subExpr));
1718*700637cbSDimitry Andric     if (v) {
1719*700637cbSDimitry Andric       // CK_NoOp can model a pointer qualification conversion, which can remove
1720*700637cbSDimitry Andric       // an array bound and change the IR type.
1721*700637cbSDimitry Andric       // FIXME: Once pointee types are removed from IR, remove this.
1722*700637cbSDimitry Andric       mlir::Type t = cgf.convertType(destTy);
1723*700637cbSDimitry Andric       if (t != v.getType())
1724*700637cbSDimitry Andric         cgf.getCIRGenModule().errorNYI("pointer qualification conversion");
1725*700637cbSDimitry Andric     }
1726*700637cbSDimitry Andric     return v;
1727*700637cbSDimitry Andric   }
1728*700637cbSDimitry Andric 
1729*700637cbSDimitry Andric   case CK_ArrayToPointerDecay:
1730*700637cbSDimitry Andric     return cgf.emitArrayToPointerDecay(subExpr).getPointer();
1731*700637cbSDimitry Andric 
1732*700637cbSDimitry Andric   case CK_NullToPointer: {
1733*700637cbSDimitry Andric     if (mustVisitNullValue(subExpr))
1734*700637cbSDimitry Andric       cgf.emitIgnoredExpr(subExpr);
1735*700637cbSDimitry Andric 
1736*700637cbSDimitry Andric     // Note that DestTy is used as the MLIR type instead of a custom
1737*700637cbSDimitry Andric     // nullptr type.
1738*700637cbSDimitry Andric     mlir::Type ty = cgf.convertType(destTy);
1739*700637cbSDimitry Andric     return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
1740*700637cbSDimitry Andric   }
1741*700637cbSDimitry Andric 
1742*700637cbSDimitry Andric   case CK_LValueToRValue:
1743*700637cbSDimitry Andric     assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
1744*700637cbSDimitry Andric     assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
1745*700637cbSDimitry Andric     return Visit(const_cast<Expr *>(subExpr));
1746*700637cbSDimitry Andric 
1747*700637cbSDimitry Andric   case CK_IntegralCast: {
1748*700637cbSDimitry Andric     ScalarConversionOpts opts;
1749*700637cbSDimitry Andric     if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
1750*700637cbSDimitry Andric       if (!ice->isPartOfExplicitCast())
1751*700637cbSDimitry Andric         opts = ScalarConversionOpts(cgf.sanOpts);
1752*700637cbSDimitry Andric     }
1753*700637cbSDimitry Andric     return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
1754*700637cbSDimitry Andric                                 ce->getExprLoc(), opts);
1755*700637cbSDimitry Andric   }
1756*700637cbSDimitry Andric 
1757*700637cbSDimitry Andric   case CK_FloatingRealToComplex:
1758*700637cbSDimitry Andric   case CK_FloatingComplexCast:
1759*700637cbSDimitry Andric   case CK_IntegralRealToComplex:
1760*700637cbSDimitry Andric   case CK_IntegralComplexCast:
1761*700637cbSDimitry Andric   case CK_IntegralComplexToFloatingComplex:
1762*700637cbSDimitry Andric   case CK_FloatingComplexToIntegralComplex:
1763*700637cbSDimitry Andric     llvm_unreachable("scalar cast to non-scalar value");
1764*700637cbSDimitry Andric 
1765*700637cbSDimitry Andric   case CK_PointerToIntegral: {
1766*700637cbSDimitry Andric     assert(!destTy->isBooleanType() && "bool should use PointerToBool");
1767*700637cbSDimitry Andric     if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
1768*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1769*700637cbSDimitry Andric                                      "strict vtable pointers");
1770*700637cbSDimitry Andric     return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));
1771*700637cbSDimitry Andric   }
1772*700637cbSDimitry Andric   case CK_ToVoid:
1773*700637cbSDimitry Andric     cgf.emitIgnoredExpr(subExpr);
1774*700637cbSDimitry Andric     return {};
1775*700637cbSDimitry Andric 
1776*700637cbSDimitry Andric   case CK_IntegralToFloating:
1777*700637cbSDimitry Andric   case CK_FloatingToIntegral:
1778*700637cbSDimitry Andric   case CK_FloatingCast:
1779*700637cbSDimitry Andric   case CK_FixedPointToFloating:
1780*700637cbSDimitry Andric   case CK_FloatingToFixedPoint: {
1781*700637cbSDimitry Andric     if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
1782*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1783*700637cbSDimitry Andric                                      "fixed point casts");
1784*700637cbSDimitry Andric       return {};
1785*700637cbSDimitry Andric     }
1786*700637cbSDimitry Andric     assert(!cir::MissingFeatures::cgFPOptionsRAII());
1787*700637cbSDimitry Andric     return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
1788*700637cbSDimitry Andric                                 ce->getExprLoc());
1789*700637cbSDimitry Andric   }
1790*700637cbSDimitry Andric 
1791*700637cbSDimitry Andric   case CK_IntegralToBoolean:
1792*700637cbSDimitry Andric     return emitIntToBoolConversion(Visit(subExpr),
1793*700637cbSDimitry Andric                                    cgf.getLoc(ce->getSourceRange()));
1794*700637cbSDimitry Andric 
1795*700637cbSDimitry Andric   case CK_PointerToBoolean:
1796*700637cbSDimitry Andric     return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());
1797*700637cbSDimitry Andric   case CK_FloatingToBoolean:
1798*700637cbSDimitry Andric     return emitFloatToBoolConversion(Visit(subExpr),
1799*700637cbSDimitry Andric                                      cgf.getLoc(subExpr->getExprLoc()));
1800*700637cbSDimitry Andric   case CK_MemberPointerToBoolean: {
1801*700637cbSDimitry Andric     mlir::Value memPtr = Visit(subExpr);
1802*700637cbSDimitry Andric     return builder.createCast(cgf.getLoc(ce->getSourceRange()),
1803*700637cbSDimitry Andric                               cir::CastKind::member_ptr_to_bool, memPtr,
1804*700637cbSDimitry Andric                               cgf.convertType(destTy));
1805*700637cbSDimitry Andric   }
1806*700637cbSDimitry Andric 
1807*700637cbSDimitry Andric   case CK_VectorSplat: {
1808*700637cbSDimitry Andric     // Create a vector object and fill all elements with the same scalar value.
1809*700637cbSDimitry Andric     assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
1810*700637cbSDimitry Andric     return builder.create<cir::VecSplatOp>(
1811*700637cbSDimitry Andric         cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
1812*700637cbSDimitry Andric         Visit(subExpr));
1813*700637cbSDimitry Andric   }
1814*700637cbSDimitry Andric 
1815*700637cbSDimitry Andric   default:
1816*700637cbSDimitry Andric     cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1817*700637cbSDimitry Andric                                    "CastExpr: ", ce->getCastKindName());
1818*700637cbSDimitry Andric   }
1819*700637cbSDimitry Andric   return {};
1820*700637cbSDimitry Andric }
1821*700637cbSDimitry Andric 
VisitCallExpr(const CallExpr * e)1822*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
1823*700637cbSDimitry Andric   if (e->getCallReturnType(cgf.getContext())->isReferenceType())
1824*700637cbSDimitry Andric     return emitLoadOfLValue(e);
1825*700637cbSDimitry Andric 
1826*700637cbSDimitry Andric   auto v = cgf.emitCallExpr(e).getValue();
1827*700637cbSDimitry Andric   assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());
1828*700637cbSDimitry Andric   return v;
1829*700637cbSDimitry Andric }
1830*700637cbSDimitry Andric 
VisitMemberExpr(MemberExpr * e)1831*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
1832*700637cbSDimitry Andric   // TODO(cir): The classic codegen calls tryEmitAsConstant() here. Folding
1833*700637cbSDimitry Andric   // constants sound like work for MLIR optimizers, but we'll keep an assertion
1834*700637cbSDimitry Andric   // for now.
1835*700637cbSDimitry Andric   assert(!cir::MissingFeatures::tryEmitAsConstant());
1836*700637cbSDimitry Andric   Expr::EvalResult result;
1837*700637cbSDimitry Andric   if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {
1838*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "Constant interger member expr");
1839*700637cbSDimitry Andric     // Fall through to emit this as a non-constant access.
1840*700637cbSDimitry Andric   }
1841*700637cbSDimitry Andric   return emitLoadOfLValue(e);
1842*700637cbSDimitry Andric }
1843*700637cbSDimitry Andric 
VisitInitListExpr(InitListExpr * e)1844*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
1845*700637cbSDimitry Andric   const unsigned numInitElements = e->getNumInits();
1846*700637cbSDimitry Andric 
1847*700637cbSDimitry Andric   if (e->hadArrayRangeDesignator()) {
1848*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
1849*700637cbSDimitry Andric     return {};
1850*700637cbSDimitry Andric   }
1851*700637cbSDimitry Andric 
1852*700637cbSDimitry Andric   if (e->getType()->isVectorType()) {
1853*700637cbSDimitry Andric     const auto vectorType =
1854*700637cbSDimitry Andric         mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
1855*700637cbSDimitry Andric 
1856*700637cbSDimitry Andric     SmallVector<mlir::Value, 16> elements;
1857*700637cbSDimitry Andric     for (Expr *init : e->inits()) {
1858*700637cbSDimitry Andric       elements.push_back(Visit(init));
1859*700637cbSDimitry Andric     }
1860*700637cbSDimitry Andric 
1861*700637cbSDimitry Andric     // Zero-initialize any remaining values.
1862*700637cbSDimitry Andric     if (numInitElements < vectorType.getSize()) {
1863*700637cbSDimitry Andric       const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
1864*700637cbSDimitry Andric           vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
1865*700637cbSDimitry Andric       std::fill_n(std::back_inserter(elements),
1866*700637cbSDimitry Andric                   vectorType.getSize() - numInitElements, zeroValue);
1867*700637cbSDimitry Andric     }
1868*700637cbSDimitry Andric 
1869*700637cbSDimitry Andric     return cgf.getBuilder().create<cir::VecCreateOp>(
1870*700637cbSDimitry Andric         cgf.getLoc(e->getSourceRange()), vectorType, elements);
1871*700637cbSDimitry Andric   }
1872*700637cbSDimitry Andric 
1873*700637cbSDimitry Andric   if (numInitElements == 0) {
1874*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(),
1875*700637cbSDimitry Andric                      "InitListExpr Non VectorType with 0 init elements");
1876*700637cbSDimitry Andric     return {};
1877*700637cbSDimitry Andric   }
1878*700637cbSDimitry Andric 
1879*700637cbSDimitry Andric   return Visit(e->getInit(0));
1880*700637cbSDimitry Andric }
1881*700637cbSDimitry Andric 
emitScalarConversion(mlir::Value src,QualType srcTy,QualType dstTy,SourceLocation loc)1882*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
1883*700637cbSDimitry Andric                                                  QualType srcTy, QualType dstTy,
1884*700637cbSDimitry Andric                                                  SourceLocation loc) {
1885*700637cbSDimitry Andric   assert(CIRGenFunction::hasScalarEvaluationKind(srcTy) &&
1886*700637cbSDimitry Andric          CIRGenFunction::hasScalarEvaluationKind(dstTy) &&
1887*700637cbSDimitry Andric          "Invalid scalar expression to emit");
1888*700637cbSDimitry Andric   return ScalarExprEmitter(*this, builder)
1889*700637cbSDimitry Andric       .emitScalarConversion(src, srcTy, dstTy, loc);
1890*700637cbSDimitry Andric }
1891*700637cbSDimitry Andric 
VisitUnaryLNot(const UnaryOperator * e)1892*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
1893*700637cbSDimitry Andric   // Perform vector logical not on comparison with zero vector.
1894*700637cbSDimitry Andric   if (e->getType()->isVectorType() &&
1895*700637cbSDimitry Andric       e->getType()->castAs<VectorType>()->getVectorKind() ==
1896*700637cbSDimitry Andric           VectorKind::Generic) {
1897*700637cbSDimitry Andric     assert(!cir::MissingFeatures::vectorType());
1898*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "vector logical not");
1899*700637cbSDimitry Andric     return {};
1900*700637cbSDimitry Andric   }
1901*700637cbSDimitry Andric 
1902*700637cbSDimitry Andric   // Compare operand to zero.
1903*700637cbSDimitry Andric   mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());
1904*700637cbSDimitry Andric 
1905*700637cbSDimitry Andric   // Invert value.
1906*700637cbSDimitry Andric   boolVal = builder.createNot(boolVal);
1907*700637cbSDimitry Andric 
1908*700637cbSDimitry Andric   // ZExt result to the expr type.
1909*700637cbSDimitry Andric   return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
1910*700637cbSDimitry Andric }
1911*700637cbSDimitry Andric 
VisitUnaryReal(const UnaryOperator * e)1912*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
1913*700637cbSDimitry Andric   // TODO(cir): handle scalar promotion.
1914*700637cbSDimitry Andric   Expr *op = e->getSubExpr();
1915*700637cbSDimitry Andric   if (op->getType()->isAnyComplexType()) {
1916*700637cbSDimitry Andric     // If it's an l-value, load through the appropriate subobject l-value.
1917*700637cbSDimitry Andric     // Note that we have to ask `e` because `op` might be an l-value that
1918*700637cbSDimitry Andric     // this won't work for, e.g. an Obj-C property.
1919*700637cbSDimitry Andric     if (e->isGLValue()) {
1920*700637cbSDimitry Andric       mlir::Location loc = cgf.getLoc(e->getExprLoc());
1921*700637cbSDimitry Andric       mlir::Value complex = cgf.emitComplexExpr(op);
1922*700637cbSDimitry Andric       return cgf.builder.createComplexReal(loc, complex);
1923*700637cbSDimitry Andric     }
1924*700637cbSDimitry Andric 
1925*700637cbSDimitry Andric     // Otherwise, calculate and project.
1926*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(),
1927*700637cbSDimitry Andric                      "VisitUnaryReal calculate and project");
1928*700637cbSDimitry Andric   }
1929*700637cbSDimitry Andric 
1930*700637cbSDimitry Andric   return Visit(op);
1931*700637cbSDimitry Andric }
1932*700637cbSDimitry Andric 
VisitUnaryImag(const UnaryOperator * e)1933*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {
1934*700637cbSDimitry Andric   // TODO(cir): handle scalar promotion.
1935*700637cbSDimitry Andric   Expr *op = e->getSubExpr();
1936*700637cbSDimitry Andric   if (op->getType()->isAnyComplexType()) {
1937*700637cbSDimitry Andric     // If it's an l-value, load through the appropriate subobject l-value.
1938*700637cbSDimitry Andric     // Note that we have to ask `e` because `op` might be an l-value that
1939*700637cbSDimitry Andric     // this won't work for, e.g. an Obj-C property.
1940*700637cbSDimitry Andric     if (e->isGLValue()) {
1941*700637cbSDimitry Andric       mlir::Location loc = cgf.getLoc(e->getExprLoc());
1942*700637cbSDimitry Andric       mlir::Value complex = cgf.emitComplexExpr(op);
1943*700637cbSDimitry Andric       return cgf.builder.createComplexImag(loc, complex);
1944*700637cbSDimitry Andric     }
1945*700637cbSDimitry Andric 
1946*700637cbSDimitry Andric     // Otherwise, calculate and project.
1947*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(),
1948*700637cbSDimitry Andric                      "VisitUnaryImag calculate and project");
1949*700637cbSDimitry Andric   }
1950*700637cbSDimitry Andric 
1951*700637cbSDimitry Andric   return Visit(op);
1952*700637cbSDimitry Andric }
1953*700637cbSDimitry Andric 
1954*700637cbSDimitry Andric /// Return the size or alignment of the type of argument of the sizeof
1955*700637cbSDimitry Andric /// expression as an integer.
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * e)1956*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
1957*700637cbSDimitry Andric     const UnaryExprOrTypeTraitExpr *e) {
1958*700637cbSDimitry Andric   const QualType typeToSize = e->getTypeOfArgument();
1959*700637cbSDimitry Andric   const mlir::Location loc = cgf.getLoc(e->getSourceRange());
1960*700637cbSDimitry Andric   if (auto kind = e->getKind();
1961*700637cbSDimitry Andric       kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
1962*700637cbSDimitry Andric     if (cgf.getContext().getAsVariableArrayType(typeToSize)) {
1963*700637cbSDimitry Andric       cgf.getCIRGenModule().errorNYI(e->getSourceRange(),
1964*700637cbSDimitry Andric                                      "sizeof operator for VariableArrayType",
1965*700637cbSDimitry Andric                                      e->getStmtClassName());
1966*700637cbSDimitry Andric       return builder.getConstant(
1967*700637cbSDimitry Andric           loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1968*700637cbSDimitry Andric                                  llvm::APSInt(llvm::APInt(64, 1), true)));
1969*700637cbSDimitry Andric     }
1970*700637cbSDimitry Andric   } else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
1971*700637cbSDimitry Andric     cgf.getCIRGenModule().errorNYI(
1972*700637cbSDimitry Andric         e->getSourceRange(), "sizeof operator for OpenMpRequiredSimdAlign",
1973*700637cbSDimitry Andric         e->getStmtClassName());
1974*700637cbSDimitry Andric     return builder.getConstant(
1975*700637cbSDimitry Andric         loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1976*700637cbSDimitry Andric                                llvm::APSInt(llvm::APInt(64, 1), true)));
1977*700637cbSDimitry Andric   }
1978*700637cbSDimitry Andric 
1979*700637cbSDimitry Andric   return builder.getConstant(
1980*700637cbSDimitry Andric       loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1981*700637cbSDimitry Andric                              e->EvaluateKnownConstInt(cgf.getContext())));
1982*700637cbSDimitry Andric }
1983*700637cbSDimitry Andric 
1984*700637cbSDimitry Andric /// Return true if the specified expression is cheap enough and side-effect-free
1985*700637cbSDimitry Andric /// enough to evaluate unconditionally instead of conditionally.  This is used
1986*700637cbSDimitry Andric /// to convert control flow into selects in some cases.
1987*700637cbSDimitry Andric /// TODO(cir): can be shared with LLVM codegen.
isCheapEnoughToEvaluateUnconditionally(const Expr * e,CIRGenFunction & cgf)1988*700637cbSDimitry Andric static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e,
1989*700637cbSDimitry Andric                                                    CIRGenFunction &cgf) {
1990*700637cbSDimitry Andric   // Anything that is an integer or floating point constant is fine.
1991*700637cbSDimitry Andric   return e->IgnoreParens()->isEvaluatable(cgf.getContext());
1992*700637cbSDimitry Andric 
1993*700637cbSDimitry Andric   // Even non-volatile automatic variables can't be evaluated unconditionally.
1994*700637cbSDimitry Andric   // Referencing a thread_local may cause non-trivial initialization work to
1995*700637cbSDimitry Andric   // occur. If we're inside a lambda and one of the variables is from the scope
1996*700637cbSDimitry Andric   // outside the lambda, that function may have returned already. Reading its
1997*700637cbSDimitry Andric   // locals is a bad idea. Also, these reads may introduce races there didn't
1998*700637cbSDimitry Andric   // exist in the source-level program.
1999*700637cbSDimitry Andric }
2000*700637cbSDimitry Andric 
VisitAbstractConditionalOperator(const AbstractConditionalOperator * e)2001*700637cbSDimitry Andric mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2002*700637cbSDimitry Andric     const AbstractConditionalOperator *e) {
2003*700637cbSDimitry Andric   CIRGenBuilderTy &builder = cgf.getBuilder();
2004*700637cbSDimitry Andric   mlir::Location loc = cgf.getLoc(e->getSourceRange());
2005*700637cbSDimitry Andric   ignoreResultAssign = false;
2006*700637cbSDimitry Andric 
2007*700637cbSDimitry Andric   // Bind the common expression if necessary.
2008*700637cbSDimitry Andric   CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2009*700637cbSDimitry Andric 
2010*700637cbSDimitry Andric   Expr *condExpr = e->getCond();
2011*700637cbSDimitry Andric   Expr *lhsExpr = e->getTrueExpr();
2012*700637cbSDimitry Andric   Expr *rhsExpr = e->getFalseExpr();
2013*700637cbSDimitry Andric 
2014*700637cbSDimitry Andric   // If the condition constant folds and can be elided, try to avoid emitting
2015*700637cbSDimitry Andric   // the condition and the dead arm.
2016*700637cbSDimitry Andric   bool condExprBool;
2017*700637cbSDimitry Andric   if (cgf.constantFoldsToBool(condExpr, condExprBool)) {
2018*700637cbSDimitry Andric     Expr *live = lhsExpr, *dead = rhsExpr;
2019*700637cbSDimitry Andric     if (!condExprBool)
2020*700637cbSDimitry Andric       std::swap(live, dead);
2021*700637cbSDimitry Andric 
2022*700637cbSDimitry Andric     // If the dead side doesn't have labels we need, just emit the Live part.
2023*700637cbSDimitry Andric     if (!cgf.containsLabel(dead)) {
2024*700637cbSDimitry Andric       if (condExprBool)
2025*700637cbSDimitry Andric         assert(!cir::MissingFeatures::incrementProfileCounter());
2026*700637cbSDimitry Andric       mlir::Value result = Visit(live);
2027*700637cbSDimitry Andric 
2028*700637cbSDimitry Andric       // If the live part is a throw expression, it acts like it has a void
2029*700637cbSDimitry Andric       // type, so evaluating it returns a null Value.  However, a conditional
2030*700637cbSDimitry Andric       // with non-void type must return a non-null Value.
2031*700637cbSDimitry Andric       if (!result && !e->getType()->isVoidType()) {
2032*700637cbSDimitry Andric         cgf.cgm.errorNYI(e->getSourceRange(),
2033*700637cbSDimitry Andric                          "throw expression in conditional operator");
2034*700637cbSDimitry Andric         result = {};
2035*700637cbSDimitry Andric       }
2036*700637cbSDimitry Andric 
2037*700637cbSDimitry Andric       return result;
2038*700637cbSDimitry Andric     }
2039*700637cbSDimitry Andric   }
2040*700637cbSDimitry Andric 
2041*700637cbSDimitry Andric   QualType condType = condExpr->getType();
2042*700637cbSDimitry Andric 
2043*700637cbSDimitry Andric   // OpenCL: If the condition is a vector, we can treat this condition like
2044*700637cbSDimitry Andric   // the select function.
2045*700637cbSDimitry Andric   if ((cgf.getLangOpts().OpenCL && condType->isVectorType()) ||
2046*700637cbSDimitry Andric       condType->isExtVectorType()) {
2047*700637cbSDimitry Andric     assert(!cir::MissingFeatures::vectorType());
2048*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "vector ternary op");
2049*700637cbSDimitry Andric   }
2050*700637cbSDimitry Andric 
2051*700637cbSDimitry Andric   if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {
2052*700637cbSDimitry Andric     if (!condType->isVectorType()) {
2053*700637cbSDimitry Andric       assert(!cir::MissingFeatures::vecTernaryOp());
2054*700637cbSDimitry Andric       cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");
2055*700637cbSDimitry Andric       return {};
2056*700637cbSDimitry Andric     }
2057*700637cbSDimitry Andric 
2058*700637cbSDimitry Andric     mlir::Value condValue = Visit(condExpr);
2059*700637cbSDimitry Andric     mlir::Value lhsValue = Visit(lhsExpr);
2060*700637cbSDimitry Andric     mlir::Value rhsValue = Visit(rhsExpr);
2061*700637cbSDimitry Andric     return builder.create<cir::VecTernaryOp>(loc, condValue, lhsValue,
2062*700637cbSDimitry Andric                                              rhsValue);
2063*700637cbSDimitry Andric   }
2064*700637cbSDimitry Andric 
2065*700637cbSDimitry Andric   // If this is a really simple expression (like x ? 4 : 5), emit this as a
2066*700637cbSDimitry Andric   // select instead of as control flow.  We can only do this if it is cheap
2067*700637cbSDimitry Andric   // and safe to evaluate the LHS and RHS unconditionally.
2068*700637cbSDimitry Andric   if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&
2069*700637cbSDimitry Andric       isCheapEnoughToEvaluateUnconditionally(rhsExpr, cgf)) {
2070*700637cbSDimitry Andric     bool lhsIsVoid = false;
2071*700637cbSDimitry Andric     mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
2072*700637cbSDimitry Andric     assert(!cir::MissingFeatures::incrementProfileCounter());
2073*700637cbSDimitry Andric 
2074*700637cbSDimitry Andric     mlir::Value lhs = Visit(lhsExpr);
2075*700637cbSDimitry Andric     if (!lhs) {
2076*700637cbSDimitry Andric       lhs = builder.getNullValue(cgf.VoidTy, loc);
2077*700637cbSDimitry Andric       lhsIsVoid = true;
2078*700637cbSDimitry Andric     }
2079*700637cbSDimitry Andric 
2080*700637cbSDimitry Andric     mlir::Value rhs = Visit(rhsExpr);
2081*700637cbSDimitry Andric     if (lhsIsVoid) {
2082*700637cbSDimitry Andric       assert(!rhs && "lhs and rhs types must match");
2083*700637cbSDimitry Andric       rhs = builder.getNullValue(cgf.VoidTy, loc);
2084*700637cbSDimitry Andric     }
2085*700637cbSDimitry Andric 
2086*700637cbSDimitry Andric     return builder.createSelect(loc, condV, lhs, rhs);
2087*700637cbSDimitry Andric   }
2088*700637cbSDimitry Andric 
2089*700637cbSDimitry Andric   mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);
2090*700637cbSDimitry Andric   CIRGenFunction::ConditionalEvaluation eval(cgf);
2091*700637cbSDimitry Andric   SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2092*700637cbSDimitry Andric   mlir::Type yieldTy{};
2093*700637cbSDimitry Andric 
2094*700637cbSDimitry Andric   auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {
2095*700637cbSDimitry Andric     CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2096*700637cbSDimitry Andric     cgf.curLexScope->setAsTernary();
2097*700637cbSDimitry Andric 
2098*700637cbSDimitry Andric     assert(!cir::MissingFeatures::incrementProfileCounter());
2099*700637cbSDimitry Andric     eval.beginEvaluation();
2100*700637cbSDimitry Andric     mlir::Value branch = Visit(expr);
2101*700637cbSDimitry Andric     eval.endEvaluation();
2102*700637cbSDimitry Andric 
2103*700637cbSDimitry Andric     if (branch) {
2104*700637cbSDimitry Andric       yieldTy = branch.getType();
2105*700637cbSDimitry Andric       b.create<cir::YieldOp>(loc, branch);
2106*700637cbSDimitry Andric     } else {
2107*700637cbSDimitry Andric       // If LHS or RHS is a throw or void expression we need to patch
2108*700637cbSDimitry Andric       // arms as to properly match yield types.
2109*700637cbSDimitry Andric       insertPoints.push_back(b.saveInsertionPoint());
2110*700637cbSDimitry Andric     }
2111*700637cbSDimitry Andric   };
2112*700637cbSDimitry Andric 
2113*700637cbSDimitry Andric   mlir::Value result = builder
2114*700637cbSDimitry Andric                            .create<cir::TernaryOp>(
2115*700637cbSDimitry Andric                                loc, condV,
2116*700637cbSDimitry Andric                                /*trueBuilder=*/
2117*700637cbSDimitry Andric                                [&](mlir::OpBuilder &b, mlir::Location loc) {
2118*700637cbSDimitry Andric                                  emitBranch(b, loc, lhsExpr);
2119*700637cbSDimitry Andric                                },
2120*700637cbSDimitry Andric                                /*falseBuilder=*/
2121*700637cbSDimitry Andric                                [&](mlir::OpBuilder &b, mlir::Location loc) {
2122*700637cbSDimitry Andric                                  emitBranch(b, loc, rhsExpr);
2123*700637cbSDimitry Andric                                })
2124*700637cbSDimitry Andric                            .getResult();
2125*700637cbSDimitry Andric 
2126*700637cbSDimitry Andric   if (!insertPoints.empty()) {
2127*700637cbSDimitry Andric     // If both arms are void, so be it.
2128*700637cbSDimitry Andric     if (!yieldTy)
2129*700637cbSDimitry Andric       yieldTy = cgf.VoidTy;
2130*700637cbSDimitry Andric 
2131*700637cbSDimitry Andric     // Insert required yields.
2132*700637cbSDimitry Andric     for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2133*700637cbSDimitry Andric       mlir::OpBuilder::InsertionGuard guard(builder);
2134*700637cbSDimitry Andric       builder.restoreInsertionPoint(toInsert);
2135*700637cbSDimitry Andric 
2136*700637cbSDimitry Andric       // Block does not return: build empty yield.
2137*700637cbSDimitry Andric       if (mlir::isa<cir::VoidType>(yieldTy)) {
2138*700637cbSDimitry Andric         builder.create<cir::YieldOp>(loc);
2139*700637cbSDimitry Andric       } else { // Block returns: set null yield value.
2140*700637cbSDimitry Andric         mlir::Value op0 = builder.getNullValue(yieldTy, loc);
2141*700637cbSDimitry Andric         builder.create<cir::YieldOp>(loc, op0);
2142*700637cbSDimitry Andric       }
2143*700637cbSDimitry Andric     }
2144*700637cbSDimitry Andric   }
2145*700637cbSDimitry Andric 
2146*700637cbSDimitry Andric   return result;
2147*700637cbSDimitry Andric }
2148*700637cbSDimitry Andric 
emitScalarPrePostIncDec(const UnaryOperator * e,LValue lv,bool isInc,bool isPre)2149*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitScalarPrePostIncDec(const UnaryOperator *e,
2150*700637cbSDimitry Andric                                                     LValue lv, bool isInc,
2151*700637cbSDimitry Andric                                                     bool isPre) {
2152*700637cbSDimitry Andric   return ScalarExprEmitter(*this, builder)
2153*700637cbSDimitry Andric       .emitScalarPrePostIncDec(e, lv, isInc, isPre);
2154*700637cbSDimitry Andric }
2155