clang 24.0.0git
CIRGenExprScalar.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Emit Expr nodes with scalar CIR types as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
15#include "CIRGenFunction.h"
16#include "CIRGenValue.h"
17
18#include "clang/AST/Expr.h"
22
23#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
24#include "mlir/IR/Location.h"
25#include "mlir/IR/Value.h"
26
27#include <cassert>
28#include <utility>
29
30using namespace clang;
31using namespace clang::CIRGen;
32
33namespace {
34
35struct BinOpInfo {
36 mlir::Value lhs;
37 mlir::Value rhs;
38 SourceRange loc;
39 QualType fullType; // Type of operands and result
40 QualType compType; // Type used for computations. Element type
41 // for vectors, otherwise same as FullType.
42 BinaryOperator::Opcode opcode; // Opcode of BinOp to perform
43 FPOptions fpFeatures;
44 const Expr *e; // Entire expr, for error unsupported. May not be binop.
45
46 /// Check if the binop computes a division or a remainder.
47 bool isDivRemOp() const {
48 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
49 opcode == BO_RemAssign;
50 }
51
52 /// Check if the binop can result in integer overflow.
53 bool mayHaveIntegerOverflow() const {
54 // Without constant input, we can't rule out overflow.
55 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
56 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
57 if (!lhsci || !rhsci)
58 return true;
59
61 // TODO(cir): For now we just assume that we might overflow
62 return true;
63 }
64
65 /// Check if at least one operand is a fixed point type. In such cases,
66 /// this operation did not follow usual arithmetic conversion and both
67 /// operands might not be of the same type.
68 bool isFixedPointOp() const {
69 // We cannot simply check the result type since comparison operations
70 // return an int.
71 if (const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
72 QualType lhstype = binOp->getLHS()->getType();
73 QualType rhstype = binOp->getRHS()->getType();
74 return lhstype->isFixedPointType() || rhstype->isFixedPointType();
75 }
76 if (const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
77 return unop->getSubExpr()->getType()->isFixedPointType();
78 return false;
79 }
80};
81
82class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
83 CIRGenFunction &cgf;
84 CIRGenBuilderTy &builder;
85 // Unlike classic codegen we set this to false or use std::exchange to read
86 // the value instead of calling TestAndClearIgnoreResultAssign to make it
87 // explicit when the value is used
88 bool ignoreResultAssign;
89
90public:
91 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
92 bool ignoreResultAssign = false)
93 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
94
95 //===--------------------------------------------------------------------===//
96 // Utilities
97 //===--------------------------------------------------------------------===//
98 mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }
99
100 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
101 mlir::Value value, CastKind kind,
102 QualType destTy);
103
104 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
105 return cgf.cgm.emitNullConstant(ty, loc);
106 }
107
108 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
109 return builder.createFloatingCast(result, cgf.convertType(promotionType));
110 }
111
112 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
113 return builder.createFloatingCast(result, cgf.convertType(exprType));
114 }
115
116 mlir::Value emitPromoted(const Expr *e, QualType promotionType);
117
118 mlir::Value maybePromoteBoolResult(mlir::Value value,
119 mlir::Type dstTy) const {
120 if (mlir::isa<cir::IntType>(dstTy))
121 return builder.createBoolToInt(value, dstTy);
122 if (mlir::isa<cir::BoolType>(dstTy))
123 return value;
124 llvm_unreachable("Can only promote integer or boolean types");
125 }
126
127 //===--------------------------------------------------------------------===//
128 // Visitor Methods
129 //===--------------------------------------------------------------------===//
130
131 mlir::Value Visit(Expr *e) {
132 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
133 }
134
135 mlir::Value VisitStmt(Stmt *s) {
136 llvm_unreachable("Statement passed to ScalarExprEmitter");
137 }
138
139 mlir::Value VisitExpr(Expr *e) {
140 cgf.getCIRGenModule().errorNYI(
141 e->getSourceRange(), "scalar expression kind: ", e->getStmtClassName());
142 return {};
143 }
144
145 mlir::Value VisitConstantExpr(ConstantExpr *e) {
146 // A constant expression of type 'void' generates no code and produces no
147 // value.
148 if (e->getType()->isVoidType())
149 return {};
150
151 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
152 if (e->isGLValue()) {
153 cgf.cgm.errorNYI(e->getSourceRange(),
154 "ScalarExprEmitter: constant expr GL Value");
155 return {};
156 }
157
158 return builder.getConstant(cgf.getLoc(e->getSourceRange()),
159 mlir::cast<mlir::TypedAttr>(result));
160 }
161
162 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: constant expr");
163 return {};
164 }
165
166 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
167 return Visit(e->getSelectedExpr());
168 }
169
170 mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
171
172 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
173 return Visit(ge->getResultExpr());
174 }
175
176 /// Emits the address of the l-value, then loads and returns the result.
177 mlir::Value emitLoadOfLValue(const Expr *e) {
178 LValue lv = cgf.emitLValue(e);
179 // FIXME: add some akin to EmitLValueAlignmentAssumption(E, V);
180 return cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
181 }
182
183 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
184 return cgf.emitCoawaitExpr(*s).getValue();
185 }
186
187 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
188 return cgf.emitCoyieldExpr(*e).getValue();
189 }
190
191 mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
192 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: unary coawait");
193 return {};
194 }
195
196 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
197 return cgf.emitLoadOfLValue(lv, loc).getValue();
198 }
199
200 // l-values
201 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
202 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
203 return cgf.emitScalarConstant(constant, e);
204
205 return emitLoadOfLValue(e);
206 }
207
208 mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) {
209 auto func = cast<cir::FuncOp>(cgf.curFn);
210 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
211 &cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName());
212 // GotoSolver collects this cir.block_address op after FlattenCFG to keep
213 // the label and wire it as an indirect-branch successor.
214 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->getSourceRange()),
215 cgf.convertType(e->getType()),
216 blockInfoAttr);
217 }
218
219 mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {
220 mlir::Type type = cgf.convertType(e->getType());
221 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
222 cir::IntAttr::get(type, e->getValue()));
223 }
224
225 mlir::Value VisitFixedPointLiteral(const FixedPointLiteral *e) {
226 mlir::Type type = cgf.convertType(e->getType());
227 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
228 cir::IntAttr::get(type, e->getValue()));
229 }
230
231 mlir::Value VisitFloatingLiteral(const FloatingLiteral *e) {
232 mlir::Type type = cgf.convertType(e->getType());
233 assert(mlir::isa<cir::FPTypeInterface>(type) &&
234 "expect floating-point type");
235 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
236 cir::FPAttr::get(type, e->getValue()));
237 }
238
239 mlir::Value VisitCharacterLiteral(const CharacterLiteral *e) {
240 mlir::Type ty = cgf.convertType(e->getType());
241 // Character literals are always stored in an unsigned (even for signed
242 // char), so allow implicit truncation here.
243 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
244 llvm::APInt apValue(intTy.getWidth(), e->getValue(),
245 /*isSigned=*/false, /*implicitTrunc=*/true);
246 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
247 cir::IntAttr::get(ty, apValue));
248 }
249
250 mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {
251 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
252 }
253
254 mlir::Value VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *e) {
255 if (e->getType()->isVoidType())
256 return {};
257
258 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
259 }
260
261 mlir::Value VisitGNUNullExpr(const GNUNullExpr *e) {
262 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
263 }
264
265 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
266
267 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
268 return builder.getConstInt(cgf.getLoc(e->getExprLoc()),
269 convertType(e->getType()), e->getPackLength());
270 }
271 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
272 return cgf.emitPseudoObjectRValue(e).getValue();
273 }
274 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
275 cgf.cgm.errorNYI(e->getSourceRange(),
276 "ScalarExprEmitter: sycl unique stable name");
277 return {};
278 }
279 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
280 assert(e->getDataElementCount() == 1);
281 auto it = e->begin();
282 llvm::APInt value = (*it)->getValue();
283 return builder.getConstInt(cgf.getLoc(e->getExprLoc()), value,
285 }
286 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
287 if (e->isGLValue())
288 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
289 e->getExprLoc());
290
291 // Otherwise, assume the mapping is the scalar directly.
292 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
293 }
294
295 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
296 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc selector");
297 return {};
298 }
299 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
300 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc protocol");
301 return {};
302 }
303 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
304 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc ivar ref");
305 return {};
306 }
307 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
308 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc message");
309 return {};
310 }
311 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
312 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc isa");
313 return {};
314 }
315 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
316 cgf.cgm.errorNYI(e->getSourceRange(),
317 "ScalarExprEmitter: objc availability check");
318 return {};
319 }
320
321 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
322 cgf.cgm.errorNYI(e->getSourceRange(),
323 "ScalarExprEmitter: matrix subscript");
324 return {};
325 }
326
327 mlir::Value VisitCastExpr(CastExpr *e);
328 mlir::Value VisitCallExpr(const CallExpr *e);
329
330 mlir::Value VisitStmtExpr(StmtExpr *e) {
331 CIRGenFunction::StmtExprEvaluation eval(cgf);
332 if (e->getType()->isVoidType()) {
333 (void)cgf.emitCompoundStmt(*e->getSubStmt());
334 return {};
335 }
336
337 Address retAlloca =
338 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
339 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
340
341 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->getType()),
342 e->getExprLoc());
343 }
344
345 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
346 ignoreResultAssign = false;
347
348 if (e->getBase()->getType()->isVectorType()) {
350
351 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
352 const mlir::Value vecValue = Visit(e->getBase());
353 const mlir::Value indexValue = Visit(e->getIdx());
354 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
355 }
356 // Just load the lvalue formed by the subscript expression.
357 return emitLoadOfLValue(e);
358 }
359
360 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
361 if (e->getNumSubExprs() == 2) {
362 // The undocumented form of __builtin_shufflevector.
363 mlir::Value inputVec = Visit(e->getExpr(0));
364 mlir::Value indexVec = Visit(e->getExpr(1));
365 return cir::VecShuffleDynamicOp::create(
366 cgf.builder, cgf.getLoc(e->getSourceRange()), inputVec, indexVec);
367 }
368
369 mlir::Value vec1 = Visit(e->getExpr(0));
370 mlir::Value vec2 = Visit(e->getExpr(1));
371
372 // The documented form of __builtin_shufflevector, where the indices are
373 // a variable number of integer constants. The constants will be stored
374 // in an ArrayAttr.
375 SmallVector<mlir::Attribute, 8> indices;
376 for (unsigned i = 2; i < e->getNumSubExprs(); ++i) {
377 indices.push_back(
378 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
379 e->getExpr(i)
380 ->EvaluateKnownConstInt(cgf.getContext())
381 .getSExtValue()));
382 }
383
384 return cir::VecShuffleOp::create(cgf.builder,
385 cgf.getLoc(e->getSourceRange()),
386 cgf.convertType(e->getType()), vec1, vec2,
387 cgf.builder.getArrayAttr(indices));
388 }
389
390 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
391 // __builtin_convertvector is an element-wise cast, and is implemented as a
392 // regular cast. The back end handles casts of vectors correctly.
393 return emitScalarConversion(Visit(e->getSrcExpr()),
394 e->getSrcExpr()->getType(), e->getType(),
395 e->getSourceRange().getBegin());
396 }
397
398 mlir::Value VisitExtVectorElementExpr(Expr *e) { return emitLoadOfLValue(e); }
399
400 mlir::Value VisitMatrixElementExpr(Expr *e) {
401 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: matrix element");
402 return {};
403 }
404
405 mlir::Value VisitMemberExpr(MemberExpr *e);
406
407 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
408 return emitLoadOfLValue(e);
409 }
410
411 mlir::Value VisitInitListExpr(InitListExpr *e);
412
413 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
414 assert(cgf.getArrayInitIndex() &&
415 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
416 return cgf.getArrayInitIndex();
417 }
418
419 mlir::Value VisitImplicitValueInitExpr(const ImplicitValueInitExpr *e) {
420 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
421 }
422
423 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
424 return VisitCastExpr(e);
425 }
426
427 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
428 return cgf.cgm.emitNullConstant(e->getType(),
429 cgf.getLoc(e->getSourceRange()));
430 }
431
432 /// Perform a pointer to boolean conversion.
433 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
434 // TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM.
435 // We might want to have a separate pass for these types of conversions.
436 return cgf.getBuilder().createPtrToBoolCast(v);
437 }
438
439 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
440 cir::BoolType boolTy = builder.getBoolTy();
441 return cir::CastOp::create(builder, loc, boolTy,
442 cir::CastKind::float_to_bool, src);
443 }
444
445 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
446 // The enumerator of an enum with an integral underlying type is lowered to
447 // that type, which can be bool. In that case the operand is already a
448 // !cir.bool, so return it -- int_to_bool requires a !cir.int source.
449 if (mlir::isa<cir::BoolType>(srcVal.getType()))
450 return srcVal;
451
452 // Because of the type rules of C, we often end up computing a
453 // logical value, then zero extending it to int, then wanting it
454 // as a logical value again.
455 // TODO: optimize this common case here or leave it for later
456 // CIR passes?
457 cir::BoolType boolTy = builder.getBoolTy();
458 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
459 srcVal);
460 }
461
462 /// Convert the specified expression value to a boolean (!cir.bool) truth
463 /// value. This is equivalent to "Val != 0".
464 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
465 mlir::Location loc) {
466 assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs");
467
468 if (srcType->isRealFloatingType())
469 return emitFloatToBoolConversion(src, loc);
470
471 if (llvm::isa<MemberPointerType>(srcType)) {
472 cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion");
473 return builder.getFalse(loc);
474 }
475
476 if (srcType->isIntegerType())
477 return emitIntToBoolConversion(src, loc);
478
479 assert(::mlir::isa<cir::PointerType>(src.getType()));
480 return emitPointerToBoolConversion(src, srcType);
481 }
482
483 // Emit a conversion from the specified type to the specified destination
484 // type, both of which are CIR scalar types.
485 struct ScalarConversionOpts {
486 bool treatBooleanAsSigned;
487 bool emitImplicitIntegerTruncationChecks;
488 bool emitImplicitIntegerSignChangeChecks;
489
490 ScalarConversionOpts()
491 : treatBooleanAsSigned(false),
492 emitImplicitIntegerTruncationChecks(false),
493 emitImplicitIntegerSignChangeChecks(false) {}
494
495 ScalarConversionOpts(clang::SanitizerSet sanOpts)
496 : treatBooleanAsSigned(false),
497 emitImplicitIntegerTruncationChecks(
498 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
499 emitImplicitIntegerSignChangeChecks(
500 sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
501 };
502
503 // Conversion from bool, integral, or floating-point to integral or
504 // floating-point. Conversions involving other types are handled elsewhere.
505 // Conversion to bool is handled elsewhere because that's a comparison against
506 // zero, not a simple cast. This handles both individual scalars and vectors.
507 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
508 QualType dstType, mlir::Type srcTy,
509 mlir::Type dstTy, ScalarConversionOpts opts) {
510 assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
511 "Internal error: matrix types not handled by this function.");
512 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
513 mlir::isa<mlir::IntegerType>(dstTy)) &&
514 "Obsolete code. Don't use mlir::IntegerType with CIR.");
515
516 mlir::Type fullDstTy = dstTy;
517 if (mlir::isa<cir::VectorType>(srcTy) &&
518 mlir::isa<cir::VectorType>(dstTy)) {
519 // Use the element types of the vectors to figure out the CastKind.
520 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
521 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
522 }
523
524 std::optional<cir::CastKind> castKind;
525
526 // Start with a null fenv attr. If this is a floating point cast, we will
527 // get the attribute from the builder.
528 cir::FenvAttr fenvAttr;
529
530 if (mlir::isa<cir::BoolType>(srcTy)) {
531 if (opts.treatBooleanAsSigned)
532 cgf.getCIRGenModule().errorNYI("signed bool");
533 if (cgf.getBuilder().isInt(dstTy)) {
534 castKind = cir::CastKind::bool_to_int;
535 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
536 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
537 castKind = cir::CastKind::bool_to_float;
538 } else {
539 llvm_unreachable("Internal error: Cast to unexpected type");
540 }
541 } else if (cgf.getBuilder().isInt(srcTy)) {
542 if (cgf.getBuilder().isInt(dstTy)) {
543 castKind = cir::CastKind::integral;
544 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
545 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
546 castKind = cir::CastKind::int_to_float;
547 } else if (mlir::isa<cir::BoolType>(dstTy)) {
548 castKind = cir::CastKind::int_to_bool;
549 } else {
550 llvm_unreachable("Internal error: Cast to unexpected type");
551 }
552 } else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
553 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
554 if (cgf.getBuilder().isInt(dstTy)) {
555 // If we can't recognize overflow as undefined behavior, assume that
556 // overflow saturates. This protects against normal optimizations if we
557 // are compiling with non-standard FP semantics.
558 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
559 cgf.getCIRGenModule().errorNYI("strict float cast overflow");
560 castKind = cir::CastKind::float_to_int;
561 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
562 // TODO: split this to createFPExt/createFPTrunc
563 return builder.createFloatingCast(src, fullDstTy);
564 } else if (mlir::isa<cir::BoolType>(dstTy)) {
565 castKind = cir::CastKind::float_to_bool;
566 } else {
567 llvm_unreachable("Internal error: Cast to unexpected type");
568 }
569 } else {
570 llvm_unreachable("Internal error: Cast from unexpected type");
571 }
572
573 assert(castKind.has_value() && "Internal error: CastKind not set.");
574 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
575 src, fenvAttr);
576 }
577
578 mlir::Value
579 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
580 return Visit(e->getReplacement());
581 }
582
583 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
584 QualType ty = ve->getType();
585
586 if (ty->isVariablyModifiedType()) {
587 cgf.cgm.errorNYI(ve->getSourceRange(),
588 "variably modified types in varargs");
589 }
590
591 return cgf.emitVAArg(ve);
592 }
593
594 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
595 return Visit(e->getSemanticForm());
596 }
597
598 mlir::Value VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *e);
599 mlir::Value
600 VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
601
602 // Unary Operators.
603 mlir::Value VisitUnaryPrePostIncDec(const UnaryOperator *e) {
604 LValue lv = cgf.emitLValue(e->getSubExpr());
605 return emitScalarPrePostIncDec(e, lv);
606 }
607 mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
608 return VisitUnaryPrePostIncDec(e);
609 }
610 mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
611 return VisitUnaryPrePostIncDec(e);
612 }
613 mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
614 return VisitUnaryPrePostIncDec(e);
615 }
616 mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
617 return VisitUnaryPrePostIncDec(e);
618 }
619
620 mlir::Value emitFixedPointIncDec(const UnaryOperator *e, mlir::Value value,
621 QualType type);
622 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv) {
623 if (cgf.getLangOpts().OpenMP)
624 cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");
625
626 QualType type = e->getSubExpr()->getType();
627
628 mlir::Value value;
629 mlir::Value input;
630
631 if (type->getAs<AtomicType>()) {
632 cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");
633 // TODO(cir): This is not correct, but it will produce reasonable code
634 // until atomic operations are implemented.
635 value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
636 input = value;
637 } else {
638 value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
639 input = value;
640 }
641
642 // NOTE: When possible, more frequent cases are handled first.
643
644 // Special case of integer increment that we have to check first: bool++.
645 // Due to promotion rules, we get:
646 // bool++ -> bool = bool + 1
647 // -> bool = (int)bool + 1
648 // -> bool = ((int)bool + 1 != 0)
649 // An interesting aspect of this is that increment is always true.
650 // Decrement does not have this property.
651 if (e->isIncrementOp() && type->isBooleanType()) {
652 value = builder.getTrue(cgf.getLoc(e->getExprLoc()));
653 } else if (type->isIntegerType()) {
654 QualType promotedType;
655 [[maybe_unused]] bool canPerformLossyDemotionCheck = false;
656 if (cgf.getContext().isPromotableIntegerType(type)) {
657 promotedType = cgf.getContext().getPromotedIntegerType(type);
658 assert(promotedType != type && "Shouldn't promote to the same type.");
659 canPerformLossyDemotionCheck = true;
660 canPerformLossyDemotionCheck &=
661 cgf.getContext().getCanonicalType(type) !=
662 cgf.getContext().getCanonicalType(promotedType);
663 canPerformLossyDemotionCheck &=
664 type->isIntegerType() && promotedType->isIntegerType();
665
666 // TODO(cir): Currently, we store bitwidths in CIR types only for
667 // integers. This might also be required for other types.
668
669 assert(
670 (!canPerformLossyDemotionCheck ||
671 type->isSignedIntegerOrEnumerationType() ||
672 promotedType->isSignedIntegerOrEnumerationType() ||
673 mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth() ==
674 mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth()) &&
675 "The following check expects that if we do promotion to different "
676 "underlying canonical type, at least one of the types (either "
677 "base or promoted) will be signed, or the bitwidths will match.");
678 }
679
681 if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
682 value = emitIncDecConsiderOverflowBehavior(e, value);
683 } else {
684 // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
685 value = emitIncOrDec(e, input, /*nsw=*/false);
686 }
687 } else if (const PointerType *ptr = type->getAs<PointerType>()) {
688 QualType type = ptr->getPointeeType();
689 if (const VariableArrayType *vla =
690 cgf.getContext().getAsVariableArrayType(type)) {
691 mlir::Location loc = cgf.getLoc(e->getSourceRange());
692 mlir::Value numElts = cgf.getVLASize(vla).numElts;
693 if (!e->isIncrementOp())
694 numElts = cgf.getBuilder().createNeg(loc, numElts, /*nsw=*/true);
696 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
697 } else {
698 // For everything else, we can just do a simple increment.
699 mlir::Location loc = cgf.getLoc(e->getSourceRange());
700 int amount = e->isIncrementOp() ? 1 : -1;
701 mlir::Value amt = builder.getSInt32(amount, loc);
703 value = builder.createPtrStride(loc, value, amt);
704 }
705 } else if (type->isVectorType()) {
706 if (type->hasIntegerRepresentation()) {
707 value = emitIncOrDec(e, input, /*nsw=*/false);
708 } else {
709 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec vector of float");
710 return {};
711 }
712 } else if (type->isRealFloatingType()) {
713 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
714
715 if (type->isHalfType() &&
716 !cgf.getContext().getLangOpts().NativeHalfType) {
717 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec half");
718 return {};
719 }
720
721 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
722 value.getType())) {
723 mlir::Location loc = cgf.getLoc(e->getExprLoc());
724 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
725 mlir::Value amount = builder.getConstFP(
726 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
727 value = e->isIncrementOp() ? builder.createFAdd(loc, value, amount)
728 : builder.createFSub(loc, value, amount);
729 } else {
730 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
731 return {};
732 }
733 } else if (type->isFixedPointType()) {
734 value = emitFixedPointIncDec(e, value, type);
735 } else {
736 assert(type->castAs<ObjCObjectPointerType>());
737 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");
738 return {};
739 }
740
741 CIRGenFunction::SourceLocRAIIObject sourceloc{
742 cgf, cgf.getLoc(e->getSourceRange())};
743
744 // Store the updated result through the lvalue
745 if (lv.isBitField())
746 value = cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);
747 else
748 cgf.emitStoreThroughLValue(RValue::get(value), lv);
749
750 // If this is a postinc, return the value read from memory, otherwise use
751 // the updated value.
752 return e->isPrefix() ? value : input;
753 }
754
755 mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,
756 mlir::Value inVal) {
757 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
758 case LangOptions::SOB_Defined:
759 return emitIncOrDec(e, inVal, /*nsw=*/false);
760 case LangOptions::SOB_Undefined:
762 return emitIncOrDec(e, inVal, /*nsw=*/true);
763 case LangOptions::SOB_Trapping:
764 if (!e->canOverflow())
765 return emitIncOrDec(e, inVal, /*nsw=*/true);
766 cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
767 return {};
768 }
769 llvm_unreachable("Unexpected signed overflow behavior kind");
770 }
771
772 mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
773 if (llvm::isa<MemberPointerType>(e->getType()))
774 return cgf.cgm.emitMemberPointerConstant(e);
775
776 return cgf.emitLValue(e->getSubExpr()).getPointer();
777 }
778
779 mlir::Value VisitUnaryDeref(const UnaryOperator *e) {
780 if (e->getType()->isVoidType())
781 return Visit(e->getSubExpr()); // the actual value should be unused
782 return emitLoadOfLValue(e);
783 }
784
785 mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
786 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
787 mlir::Value result = VisitUnaryPlus(e, promotionType);
788 if (result && !promotionType.isNull())
789 return emitUnPromotedValue(result, e->getType());
790 return result;
791 }
792
793 mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType) {
794 ignoreResultAssign = false;
795 if (!promotionType.isNull())
796 return cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
797 return Visit(e->getSubExpr());
798 }
799
800 mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
801 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
802 mlir::Value result = VisitUnaryMinus(e, promotionType);
803 if (result && !promotionType.isNull())
804 return emitUnPromotedValue(result, e->getType());
805 return result;
806 }
807
808 mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType) {
809 ignoreResultAssign = false;
810 mlir::Value operand;
811 if (!promotionType.isNull())
812 operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
813 else
814 operand = Visit(e->getSubExpr());
815
816 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
817
818 if (cir::isFPOrVectorOfFPType(operand.getType()))
819 return builder.createOrFold<cir::FNegOp>(loc, operand);
820
821 // TODO(cir): We might have to change this to support overflow trapping.
822 // Classic codegen routes unary minus through emitSub to ensure
823 // that the overflow behavior is handled correctly.
824 bool nsw = e->getType()->isSignedIntegerType() &&
825 cgf.getLangOpts().getSignedOverflowBehavior() !=
826 LangOptions::SOB_Defined;
827
828 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
829 }
830
831 mlir::Value emitIncOrDec(const UnaryOperator *e, mlir::Value input,
832 bool nsw = false) {
833 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
834 return e->isIncrementOp()
835 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
836 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
837 }
838
839 mlir::Value VisitUnaryNot(const UnaryOperator *e) {
840 ignoreResultAssign = false;
841 mlir::Value op = Visit(e->getSubExpr());
842 return builder.createOrFold<cir::NotOp>(
843 cgf.getLoc(e->getSourceRange().getBegin()), op);
844 }
845
846 mlir::Value VisitUnaryLNot(const UnaryOperator *e);
847
848 mlir::Value VisitUnaryReal(const UnaryOperator *e);
849 mlir::Value VisitUnaryImag(const UnaryOperator *e);
850 mlir::Value VisitRealImag(const UnaryOperator *e,
851 QualType promotionType = QualType());
852
853 mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
854 return Visit(e->getSubExpr());
855 }
856
857 // C++
858 mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e) {
859 return emitLoadOfLValue(e);
860 }
861 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
862 ASTContext &ctx = cgf.getContext();
863 APValue evaluated =
864 e->EvaluateInContext(ctx, cgf.curSourceLocExprScope.getDefaultExpr());
865 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
866 e->getLocation(), evaluated, e->getType());
867 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
868 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
869 typedAttr);
870 }
871 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
872 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
873 return Visit(dae->getExpr());
874 }
875 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
876 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
877 return Visit(die->getExpr());
878 }
879
880 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
881
882 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
883 mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
884 return cgf.emitCXXNewExpr(e);
885 }
886 mlir::Value VisitCXXDeleteExpr(const CXXDeleteExpr *e) {
887 cgf.emitCXXDeleteExpr(e);
888 return {};
889 }
890 mlir::Value VisitTypeTraitExpr(const TypeTraitExpr *e) {
891 // We diverge slightly from classic codegen here because CIR has stricter
892 // typing. In LLVM IR, constant folding covers up some potential type
893 // mismatches such as bool-to-int conversions that would fail the verifier
894 // in CIR. To make things work, we need to be sure we only emit a bool value
895 // if the expression type is bool.
896 mlir::Location loc = cgf.getLoc(e->getExprLoc());
897 if (e->isStoredAsBoolean()) {
898 if (e->getType()->isBooleanType())
899 return builder.getBool(e->getBoolValue(), loc);
900 assert(e->getType()->isIntegerType() &&
901 "Expected int type for TypeTraitExpr");
902 return builder.getConstInt(loc, cgf.convertType(e->getType()),
903 (uint64_t)e->getBoolValue());
904 }
905 assert(e->getType()->isIntegerType() && "not a scalar type trait");
906 return builder.getConstInt(loc, e->getAPValue().getInt());
907 }
908 mlir::Value
909 VisitConceptSpecializationExpr(const ConceptSpecializationExpr *e) {
910 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
911 }
912 mlir::Value VisitRequiresExpr(const RequiresExpr *e) {
913 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
914 }
915 mlir::Value VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *e) {
916 mlir::Type type = cgf.convertType(e->getType());
917 mlir::Location loc = cgf.getLoc(e->getExprLoc());
918 return builder.getConstInt(loc, type, e->getValue());
919 }
920 mlir::Value VisitExpressionTraitExpr(const ExpressionTraitExpr *e) {
921 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
922 }
923 mlir::Value VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *e) {
924 cgf.cgm.errorNYI(e->getSourceRange(),
925 "ScalarExprEmitter: cxx pseudo destructor");
926 return {};
927 }
928 mlir::Value VisitCXXThrowExpr(const CXXThrowExpr *e) {
929 cgf.emitCXXThrowExpr(e);
930 return {};
931 }
932
933 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
934 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
935 }
936
937 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
938 QualType dstTy, mlir::Location loc);
939
940 /// Emit a conversion from the specified type to the specified destination
941 /// type, both of which are CIR scalar types.
942 /// TODO: do we need ScalarConversionOpts here? Should be done in another
943 /// pass.
944 mlir::Value
945 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
946 SourceLocation loc,
947 ScalarConversionOpts opts = ScalarConversionOpts()) {
948 // All conversions involving fixed point types should be handled by the
949 // emitFixedPoint family functions. This is done to prevent bloating up
950 // this function more, and although fixed point numbers are represented by
951 // integers, we do not want to follow any logic that assumes they should be
952 // treated as integers.
953 if (srcType->isFixedPointType()) {
954 if (dstType->isBooleanType()) {
955 cir::BoolType boolTy = builder.getBoolTy();
956 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
957 cir::CastKind::int_to_bool, src);
958 }
959
960 if (dstType->isFixedPointType() || dstType->isIntegerType() ||
961 dstType->isRealFloatingType())
962 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
963
964 llvm_unreachable("Unhandled scalar conversion from a fixed point type to "
965 "another type.");
966 } else if (dstType->isFixedPointType()) {
967 if (srcType->isIntegerType() || srcType->isRealFloatingType()) {
968 // This also includes converting booleans and enums to fixed point
969 // types.
970 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
971 }
972
973 llvm_unreachable("Unhandled scalar conversion to a fixed point type from "
974 "another type.");
975 }
976
977 srcType = srcType.getCanonicalType();
978 dstType = dstType.getCanonicalType();
979 if (srcType == dstType) {
980 if (opts.emitImplicitIntegerSignChangeChecks)
981 cgf.getCIRGenModule().errorNYI(loc,
982 "implicit integer sign change checks");
983 return src;
984 }
985
986 if (dstType->isVoidType())
987 return {};
988
989 mlir::Type mlirSrcType = src.getType();
990
991 // Handle conversions to bool first, they are special: comparisons against
992 // 0.
993 if (dstType->isBooleanType())
994 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
995
996 mlir::Type mlirDstType = cgf.convertType(dstType);
997
998 if (srcType->isHalfType() &&
999 !cgf.getContext().getLangOpts().NativeHalfType) {
1000 // Cast to FP using the intrinsic if the half type itself isn't supported.
1001 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1002 // Cast to other types through float, using FPExt, depending on whether
1003 // the half type itself is supported (as opposed to operations on half,
1004 // available with NativeHalfType).
1005 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1006 cgf.floatTy);
1007 srcType = cgf.getContext().FloatTy;
1008 mlirSrcType = cgf.floatTy;
1009 }
1010 }
1011
1012 // TODO(cir): LLVM codegen ignore conversions like int -> uint,
1013 // is there anything to be done for CIR here?
1014 if (mlirSrcType == mlirDstType) {
1015 if (opts.emitImplicitIntegerSignChangeChecks)
1016 cgf.getCIRGenModule().errorNYI(loc,
1017 "implicit integer sign change checks");
1018 return src;
1019 }
1020
1021 // Handle pointer conversions next: pointers can only be converted to/from
1022 // other pointers and integers. Check for pointer types in terms of LLVM, as
1023 // some native types (like Obj-C id) may map to a pointer type.
1024 if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1025 cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
1026 return builder.getNullPtr(dstPT, src.getLoc());
1027 }
1028
1029 if (isa<cir::PointerType>(mlirSrcType)) {
1030 // Must be an ptr to int cast.
1031 assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");
1032 return builder.createPtrToInt(src, mlirDstType);
1033 }
1034
1035 // A scalar can be splatted to an extended vector of the same element type
1036 if (dstType->isExtVectorType() && !srcType->isVectorType()) {
1037 // Sema should add casts to make sure that the source expression's type
1038 // is the same as the vector's element type (sans qualifiers)
1039 assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1040 srcType.getTypePtr() &&
1041 "Splatted expr doesn't match with vector element type?");
1042
1043 cgf.getCIRGenModule().errorNYI(loc, "vector splatting");
1044 return {};
1045 }
1046
1047 if (srcType->isMatrixType() && dstType->isMatrixType()) {
1048 cgf.getCIRGenModule().errorNYI(loc,
1049 "matrix type to matrix type conversion");
1050 return {};
1051 }
1052 assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
1053 "Internal error: conversion between matrix type and scalar type");
1054
1055 // Finally, we have the arithmetic types or vectors of arithmetic types.
1056 mlir::Value res = nullptr;
1057 mlir::Type resTy = mlirDstType;
1058
1059 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1060
1061 if (mlirDstType != resTy) {
1062 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1063 resTy);
1064 }
1065
1066 if (opts.emitImplicitIntegerTruncationChecks)
1067 cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");
1068
1069 if (opts.emitImplicitIntegerSignChangeChecks)
1070 cgf.getCIRGenModule().errorNYI(loc,
1071 "implicit integer sign change checks");
1072
1073 return res;
1074 }
1075
1076 BinOpInfo emitBinOps(const BinaryOperator *e,
1077 QualType promotionType = QualType()) {
1078 ignoreResultAssign = false;
1079 BinOpInfo result;
1080 result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
1081 result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
1082 if (!promotionType.isNull())
1083 result.fullType = promotionType;
1084 else
1085 result.fullType = e->getType();
1086 result.compType = result.fullType;
1087 if (const auto *vecType = result.fullType->getAs<VectorType>())
1088 result.compType = vecType->getElementType();
1089 result.opcode = e->getOpcode();
1090 result.loc = e->getSourceRange();
1091 result.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1092 result.e = e;
1093 return result;
1094 }
1095
1096 mlir::Value emitMul(const BinOpInfo &ops);
1097 mlir::Value emitDiv(const BinOpInfo &ops);
1098 mlir::Value emitRem(const BinOpInfo &ops);
1099 mlir::Value emitAdd(const BinOpInfo &ops);
1100 mlir::Value emitSub(const BinOpInfo &ops);
1101 mlir::Value emitShl(const BinOpInfo &ops);
1102 mlir::Value emitShr(const BinOpInfo &ops);
1103 mlir::Value emitAnd(const BinOpInfo &ops);
1104 mlir::Value emitXor(const BinOpInfo &ops);
1105 mlir::Value emitOr(const BinOpInfo &ops);
1106
1107 mlir::Value emitFixedPointBinOp(const BinOpInfo &ops);
1108
1109 LValue emitCompoundAssignLValue(
1110 const CompoundAssignOperator *e,
1111 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
1112 mlir::Value &result);
1113 mlir::Value
1114 emitCompoundAssign(const CompoundAssignOperator *e,
1115 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
1116
1117 // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
1118 // codegen.
1119 QualType getPromotionType(QualType ty) {
1120 const clang::ASTContext &ctx = cgf.getContext();
1121 if (auto *complexTy = ty->getAs<ComplexType>()) {
1122 QualType elementTy = complexTy->getElementType();
1123 if (elementTy.UseExcessPrecision(ctx))
1124 return ctx.getComplexType(ctx.FloatTy);
1125 }
1126
1127 if (ty.UseExcessPrecision(cgf.getContext())) {
1128 if (auto *vt = ty->getAs<VectorType>()) {
1129 unsigned numElements = vt->getNumElements();
1130 return ctx.getVectorType(ctx.FloatTy, numElements, vt->getVectorKind());
1131 }
1132 return cgf.getContext().FloatTy;
1133 }
1134
1135 return QualType();
1136 }
1137
1138// Binary operators and binary compound assignment operators.
1139#define HANDLEBINOP(OP) \
1140 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1141 QualType promotionTy = getPromotionType(e->getType()); \
1142 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1143 if (result && !promotionTy.isNull()) \
1144 result = emitUnPromotedValue(result, e->getType()); \
1145 return result; \
1146 } \
1147 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1148 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1149 }
1150
1151 HANDLEBINOP(Mul)
1152 HANDLEBINOP(Div)
1153 HANDLEBINOP(Rem)
1154 HANDLEBINOP(Add)
1155 HANDLEBINOP(Sub)
1156 HANDLEBINOP(Shl)
1157 HANDLEBINOP(Shr)
1159 HANDLEBINOP(Xor)
1161#undef HANDLEBINOP
1162
1163 cir::CmpOpKind clangCmpToCIRCmp(clang::BinaryOperatorKind clangCmp) {
1164 switch (clangCmp) {
1165 case BO_LT:
1166 return cir::CmpOpKind::lt;
1167 case BO_GT:
1168 return cir::CmpOpKind::gt;
1169 case BO_LE:
1170 return cir::CmpOpKind::le;
1171 case BO_GE:
1172 return cir::CmpOpKind::ge;
1173 case BO_EQ:
1174 return cir::CmpOpKind::eq;
1175 case BO_NE:
1176 return cir::CmpOpKind::ne;
1177 default:
1178 llvm_unreachable("unsupported comparison kind for cir.cmp");
1179 }
1180 }
1181
1182 mlir::Value emitCmp(const BinaryOperator *e) {
1183 ignoreResultAssign = false;
1184 const mlir::Location loc = cgf.getLoc(e->getExprLoc());
1185 mlir::Value result;
1186 QualType lhsTy = e->getLHS()->getType();
1187 QualType rhsTy = e->getRHS()->getType();
1188
1189 cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
1190 if (lhsTy->getAs<MemberPointerType>()) {
1192 assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
1193 mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
1194 mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
1195 result = builder.createCompare(loc, kind, lhs, rhs);
1196 } else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
1197 BinOpInfo boInfo = emitBinOps(e);
1198 mlir::Value lhs = boInfo.lhs;
1199 mlir::Value rhs = boInfo.rhs;
1200
1201 if (lhsTy->isVectorType()) {
1202 if (!e->getType()->isVectorType()) {
1203 // If AltiVec, the comparison results in a numeric type, so we use
1204 // intrinsics comparing vectors and giving 0 or 1 as a result
1205 cgf.cgm.errorNYI(loc, "AltiVec comparison");
1206 } else {
1207 // Other kinds of vectors. Element-wise comparison returning
1208 // a vector.
1209 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1210 cgf.convertType(boInfo.fullType), kind,
1211 boInfo.lhs, boInfo.rhs);
1212 }
1213 } else if (boInfo.isFixedPointOp()) {
1214 result = emitFixedPointBinOp(boInfo);
1215 } else {
1216 // integers and pointers
1217 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1218 mlir::isa<cir::PointerType>(lhs.getType()) &&
1219 mlir::isa<cir::PointerType>(rhs.getType())) {
1220 cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");
1221 }
1222 result = builder.createCompare(loc, kind, lhs, rhs);
1223 }
1224 } else {
1225 assert((e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE) &&
1226 "Complex Comparison: can only be an equality comparison");
1227
1228 mlir::Value lhs;
1229 if (lhsTy->isAnyComplexType()) {
1230 lhs = cgf.emitComplexExpr(e->getLHS());
1231 } else {
1232 mlir::Value lhsReal = Visit(e->getLHS());
1233 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1234 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1235 }
1236
1237 mlir::Value rhs;
1238 if (rhsTy->isAnyComplexType()) {
1239 rhs = cgf.emitComplexExpr(e->getRHS());
1240 } else {
1241 mlir::Value rhsReal = Visit(e->getRHS());
1242 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1243 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1244 }
1245
1246 result = builder.createCompare(loc, kind, lhs, rhs);
1247 }
1248
1249 return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
1250 e->getExprLoc());
1251 }
1252
1253// Comparisons.
1254#define VISITCOMP(CODE) \
1255 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1256 VISITCOMP(LT)
1257 VISITCOMP(GT)
1258 VISITCOMP(LE)
1259 VISITCOMP(GE)
1260 VISITCOMP(EQ)
1261 VISITCOMP(NE)
1262#undef VISITCOMP
1263
1264 mlir::Value VisitBinAssign(const BinaryOperator *e) {
1265 const bool ignore = std::exchange(ignoreResultAssign, false);
1266
1267 mlir::Value rhs;
1268 LValue lhs;
1269
1270 switch (e->getLHS()->getType().getObjCLifetime()) {
1276 break;
1278 // __block variables need to have the rhs evaluated first, plus this
1279 // should improve codegen just a little.
1280 rhs = Visit(e->getRHS());
1282 // TODO(cir): This needs to be emitCheckedLValue() once we support
1283 // sanitizers
1284 lhs = cgf.emitLValue(e->getLHS());
1285
1286 // Store the value into the LHS. Bit-fields are handled specially because
1287 // the result is altered by the store, i.e., [C99 6.5.16p1]
1288 // 'An assignment expression has the value of the left operand after the
1289 // assignment...'.
1290 if (lhs.isBitField()) {
1292 cgf, cgf.getLoc(e->getSourceRange())};
1293 rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);
1294 } else {
1295 cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
1297 cgf, cgf.getLoc(e->getSourceRange())};
1298 cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);
1299 }
1300 }
1301
1302 // If the result is clearly ignored, return now.
1303 if (ignore)
1304 return nullptr;
1305
1306 // The result of an assignment in C is the assigned r-value.
1307 if (!cgf.getLangOpts().CPlusPlus)
1308 return rhs;
1309
1310 // If the lvalue is non-volatile, return the computed value of the
1311 // assignment.
1312 if (!lhs.isVolatile())
1313 return rhs;
1314
1315 // Otherwise, reload the value.
1316 return emitLoadOfLValue(lhs, e->getExprLoc());
1317 }
1318
1319 mlir::Value VisitBinComma(const BinaryOperator *e) {
1320 cgf.emitIgnoredExpr(e->getLHS());
1321 // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.
1322 return Visit(e->getRHS());
1323 }
1324
1325 mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {
1326 if (e->getType()->isVectorType()) {
1327 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1328 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1329 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1330
1331 mlir::Value lhs = Visit(e->getLHS());
1332 mlir::Value rhs = Visit(e->getRHS());
1333
1334 auto cmpOpKind = cir::CmpOpKind::ne;
1335 mlir::Type resTy = cgf.convertType(e->getType());
1336 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1337 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1338 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1339 return builder.createIntCast(vecOr, resTy);
1340 }
1341
1343 mlir::Type resTy = cgf.convertType(e->getType());
1344 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1345
1346 CIRGenFunction::ConditionalEvaluation eval(cgf);
1347
1348 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1349 auto resOp = cir::TernaryOp::create(
1350 builder, loc, lhsCondV, /*trueBuilder=*/
1351 [&](mlir::OpBuilder &b, mlir::Location loc) {
1352 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1353 b.getInsertionBlock()};
1354 cgf.curLexScope->setAsTernary();
1355 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1356 lexScope.forceCleanup({&res});
1357 cir::YieldOp::create(b, loc, res);
1358 },
1359 /*falseBuilder*/
1360 [&](mlir::OpBuilder &b, mlir::Location loc) {
1361 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1362 b.getInsertionBlock()};
1363 cgf.curLexScope->setAsTernary();
1364 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1365 cir::YieldOp::create(b, loc, res.getRes());
1366 });
1367 return maybePromoteBoolResult(resOp.getResult(), resTy);
1368 }
1369
1370 mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {
1371 if (e->getType()->isVectorType()) {
1372 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1373 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1374 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1375
1376 mlir::Value lhs = Visit(e->getLHS());
1377 mlir::Value rhs = Visit(e->getRHS());
1378
1379 auto cmpOpKind = cir::CmpOpKind::ne;
1380 mlir::Type resTy = cgf.convertType(e->getType());
1381 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1382 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1383 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1384 return builder.createIntCast(vecOr, resTy);
1385 }
1386
1388 mlir::Type resTy = cgf.convertType(e->getType());
1389 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1390
1391 CIRGenFunction::ConditionalEvaluation eval(cgf);
1392
1393 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1394 auto resOp = cir::TernaryOp::create(
1395 builder, loc, lhsCondV, /*trueBuilder=*/
1396 [&](mlir::OpBuilder &b, mlir::Location loc) {
1397 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1398 b.getInsertionBlock()};
1399 cgf.curLexScope->setAsTernary();
1400 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1401 cir::YieldOp::create(b, loc, res.getRes());
1402 },
1403 /*falseBuilder*/
1404 [&](mlir::OpBuilder &b, mlir::Location loc) {
1405 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1406 b.getInsertionBlock()};
1407 cgf.curLexScope->setAsTernary();
1408 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1409 lexScope.forceCleanup({&res});
1410 cir::YieldOp::create(b, loc, res);
1411 });
1412
1413 return maybePromoteBoolResult(resOp.getResult(), resTy);
1414 }
1415
1416 mlir::Value VisitBinPtrMemD(const BinaryOperator *e) {
1417 return emitLoadOfLValue(e);
1418 }
1419
1420 mlir::Value VisitBinPtrMemI(const BinaryOperator *e) {
1421 return emitLoadOfLValue(e);
1422 }
1423
1424 // Other Operators.
1425 mlir::Value VisitBlockExpr(const BlockExpr *e) {
1426 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: block");
1427 return {};
1428 }
1429
1430 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1431 return Visit(e->getChosenSubExpr());
1432 }
1433
1434 mlir::Value VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1435 cgf.cgm.errorNYI(e->getSourceRange(),
1436 "ScalarExprEmitter: objc string literal");
1437 return {};
1438 }
1439 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1440 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc boxed");
1441 return {};
1442 }
1443 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1444 cgf.cgm.errorNYI(e->getSourceRange(),
1445 "ScalarExprEmitter: objc array literal");
1446 return {};
1447 }
1448 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1449 cgf.cgm.errorNYI(e->getSourceRange(),
1450 "ScalarExprEmitter: objc dictionary literal");
1451 return {};
1452 }
1453
1454 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1455 mlir::Value src, unsigned numElementsDst) {
1456 static constexpr int64_t mask[] = {0, 1, 2, -1};
1457 return builder.createVecShuffle(
1458 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1459 }
1460
1461 // Create cast instructions for converting MLIR value \p Src to MLIR type \p
1462 // DstTy. \p Src has the same size as \p DstTy. Both are single value types
1463 // but could be scalar or vectors of different lengths, and either can be
1464 // pointer.
1465 //
1466 // There are 4 cases:
1467 // 1. non-pointer -> non-pointer : needs 1 bitcast
1468 // 2. pointer -> pointer : needs 1 bitcast or addrspacecast
1469 // 3. pointer -> non-pointer
1470 // a) pointer -> intptr_t : needs 1 ptrtoint
1471 // b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast
1472 // 4. non-pointer -> pointer
1473 // a) intptr_t -> pointer : needs 1 inttoptr
1474 // b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr
1475 //
1476 // Note: for cases 3b and 4b two casts are required since LLVM casts do not
1477 // allow casting directly between pointer types and non-integer non-pointer
1478 // types.
1479 mlir::Value createCastsForTypeOfSameSize(mlir::Value src, mlir::Type dstTy) {
1480 mlir::Type srcTy = src.getType();
1481
1482 // Case 1.
1483 if (!isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy))
1484 return builder.createBitcast(src, dstTy);
1485
1486 // Case 2.
1487 if (isa<cir::PointerType>(srcTy) && isa<cir::PointerType>(dstTy)) {
1488 cgf.cgm.errorNYI(
1489 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1490 return {};
1491 }
1492
1493 // Case 3.
1494 if (isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy)) {
1495 if (!isa<cir::IntType>(dstTy)) {
1496 cgf.cgm.errorNYI(
1497 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1498 }
1499
1500 cgf.cgm.errorNYI(
1501 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1502 return {};
1503 }
1504
1505 // Case 4b.
1506 if (!isa<cir::IntType>(srcTy)) {
1507 cgf.cgm.errorNYI(
1508 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1509 return {};
1510 }
1511 // Cases 4a and 4b.
1512 return builder.createIntToPtr(src, dstTy);
1513 }
1514
1515 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1516 mlir::Value src = cgf.emitScalarExpr(e->getSrcExpr());
1517 mlir::Type srcTy = src.getType();
1518 mlir::Type dstTy = cgf.convertType(e->getType());
1519
1520 unsigned numElementsSrc = isa<cir::VectorType>(srcTy)
1521 ? cast<cir::VectorType>(srcTy).getSize()
1522 : 0;
1523 unsigned numElementsDst = isa<cir::VectorType>(dstTy)
1524 ? cast<cir::VectorType>(dstTy).getSize()
1525 : 0;
1526
1527 // Use bit vector expansion for ext_vector_type boolean vectors.
1528 if (e->getType()->isExtVectorBoolType()) {
1529 cgf.cgm.errorNYI(e->getSourceRange(),
1530 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1531 return {};
1532 }
1533
1534 // Going from vec3 to non-vec3 is a special case and requires a shuffle
1535 // vector to get a vec4, then a bitcast if the target type is different.
1536 if (numElementsSrc == 3 && numElementsDst != 3) {
1537 cgf.cgm.errorNYI(e->getSourceRange(),
1538 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1539 "numElemsDst != 3");
1540 return {};
1541 }
1542
1543 // Going from non-vec3 to vec3 is a special case and requires a bitcast
1544 // to vec4 if the original type is not vec4, then a shuffle vector to
1545 // get a vec3.
1546 if (numElementsSrc != 3 && numElementsDst == 3) {
1547 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1548 auto dstElemTy = cast<cir::VectorType>(dstTy).getElementType();
1549 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1550 src = createCastsForTypeOfSameSize(src, dstVec4Ty);
1551 src = convertVec3AndVec4(builder, loc, src, 3);
1552 return src;
1553 }
1554
1555 return createCastsForTypeOfSameSize(src, dstTy);
1556 }
1557
1558 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1559 return cgf.emitAtomicExpr(e).getValue();
1560 }
1561};
1562
1563LValue ScalarExprEmitter::emitCompoundAssignLValue(
1564 const CompoundAssignOperator *e,
1565 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
1566 mlir::Value &result) {
1568 return cgf.emitScalarCompoundAssignWithComplex(e, result);
1569
1570 QualType lhsTy = e->getLHS()->getType();
1571 BinOpInfo opInfo;
1572
1573 // Emit the RHS first. __block variables need to have the rhs evaluated
1574 // first, plus this should improve codegen a little.
1575
1576 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
1577 if (promotionTypeCR.isNull())
1578 promotionTypeCR = e->getComputationResultType();
1579
1580 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
1581 QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
1582
1583 if (!promotionTypeRHS.isNull())
1584 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
1585 else
1586 opInfo.rhs = Visit(e->getRHS());
1587
1588 opInfo.fullType = promotionTypeCR;
1589 opInfo.compType = opInfo.fullType;
1590 if (const auto *vecType = opInfo.fullType->getAs<VectorType>())
1591 opInfo.compType = vecType->getElementType();
1592 opInfo.opcode = e->getOpcode();
1593 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1594 opInfo.e = e;
1595 opInfo.loc = e->getSourceRange();
1596
1597 // Load/convert the LHS
1598 LValue lhsLV = cgf.emitLValue(e->getLHS());
1599
1600 if (lhsTy->getAs<AtomicType>()) {
1601 cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
1602 return LValue();
1603 }
1604
1605 opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
1606
1607 CIRGenFunction::SourceLocRAIIObject sourceloc{
1608 cgf, cgf.getLoc(e->getSourceRange())};
1609 SourceLocation loc = e->getExprLoc();
1610 if (!promotionTypeLHS.isNull())
1611 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1612 else
1613 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1614 e->getComputationLHSType(), loc);
1615
1616 // Expand the binary operator.
1617 result = (this->*func)(opInfo);
1618
1619 // Convert the result back to the LHS type,
1620 // potentially with Implicit Conversion sanitizer check.
1621 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1622 ScalarConversionOpts(cgf.sanOpts));
1623
1624 // Store the result value into the LHS lvalue. Bit-fields are handled
1625 // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
1626 // 'An assignment expression has the value of the left operand after the
1627 // assignment...'.
1628 if (lhsLV.isBitField())
1629 cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);
1630 else
1631 cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
1632
1633 if (cgf.getLangOpts().OpenMP)
1634 cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
1635
1636 return lhsLV;
1637}
1638
1639mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1640 mlir::Value value,
1641 CastKind kind,
1642 QualType destTy) {
1643 cir::CastKind castOpKind;
1644 switch (kind) {
1645 case CK_FloatingComplexToReal:
1646 castOpKind = cir::CastKind::float_complex_to_real;
1647 break;
1648 case CK_IntegralComplexToReal:
1649 castOpKind = cir::CastKind::int_complex_to_real;
1650 break;
1651 case CK_FloatingComplexToBoolean:
1652 castOpKind = cir::CastKind::float_complex_to_bool;
1653 break;
1654 case CK_IntegralComplexToBoolean:
1655 castOpKind = cir::CastKind::int_complex_to_bool;
1656 break;
1657 default:
1658 llvm_unreachable("invalid complex-to-scalar cast kind");
1659 }
1660
1661 return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));
1662}
1663
1664mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
1665 QualType promotionType) {
1666 e = e->IgnoreParens();
1667 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
1668 switch (bo->getOpcode()) {
1669#define HANDLE_BINOP(OP) \
1670 case BO_##OP: \
1671 return emit##OP(emitBinOps(bo, promotionType));
1672 HANDLE_BINOP(Add)
1673 HANDLE_BINOP(Sub)
1674 HANDLE_BINOP(Mul)
1675 HANDLE_BINOP(Div)
1676#undef HANDLE_BINOP
1677 default:
1678 break;
1679 }
1680 } else if (const auto *uo = dyn_cast<UnaryOperator>(e)) {
1681 switch (uo->getOpcode()) {
1682 case UO_Imag:
1683 case UO_Real:
1684 return VisitRealImag(uo, promotionType);
1685 case UO_Minus:
1686 return VisitUnaryMinus(uo, promotionType);
1687 case UO_Plus:
1688 return VisitUnaryPlus(uo, promotionType);
1689 default:
1690 break;
1691 }
1692 }
1693 mlir::Value result = Visit(const_cast<Expr *>(e));
1694 if (result) {
1695 if (!promotionType.isNull())
1696 return emitPromotedValue(result, promotionType);
1697 return emitUnPromotedValue(result, e->getType());
1698 }
1699 return result;
1700}
1701
1702mlir::Value ScalarExprEmitter::emitCompoundAssign(
1703 const CompoundAssignOperator *e,
1704 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
1705
1706 bool ignore = std::exchange(ignoreResultAssign, false);
1707 mlir::Value rhs;
1708 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1709
1710 // If the result is clearly ignored, return now.
1711 if (ignore)
1712 return {};
1713
1714 // The result of an assignment in C is the assigned r-value.
1715 if (!cgf.getLangOpts().CPlusPlus)
1716 return rhs;
1717
1718 // If the lvalue is non-volatile, return the computed value of the assignment.
1719 if (!lhs.isVolatile())
1720 return rhs;
1721
1722 // Otherwise, reload the value.
1723 return emitLoadOfLValue(lhs, e->getExprLoc());
1724}
1725
1726mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1727 CIRGenFunction::FullExprCleanupScope scope(cgf, e->getSubExpr());
1728 mlir::Value v = Visit(e->getSubExpr());
1729 // Defend against dominance problems caused by jumps out of expression
1730 // evaluation through the shared cleanup block.
1731 scope.exit({&v});
1732 return v;
1733}
1734
1735} // namespace
1736
1737LValue
1739 ScalarExprEmitter emitter(*this, builder);
1740 mlir::Value result;
1741 switch (e->getOpcode()) {
1742#define COMPOUND_OP(Op) \
1743 case BO_##Op##Assign: \
1744 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1745 result)
1746 COMPOUND_OP(Mul);
1747 COMPOUND_OP(Div);
1748 COMPOUND_OP(Rem);
1749 COMPOUND_OP(Add);
1750 COMPOUND_OP(Sub);
1751 COMPOUND_OP(Shl);
1752 COMPOUND_OP(Shr);
1754 COMPOUND_OP(Xor);
1755 COMPOUND_OP(Or);
1756#undef COMPOUND_OP
1757
1758 case BO_PtrMemD:
1759 case BO_PtrMemI:
1760 case BO_Mul:
1761 case BO_Div:
1762 case BO_Rem:
1763 case BO_Add:
1764 case BO_Sub:
1765 case BO_Shl:
1766 case BO_Shr:
1767 case BO_LT:
1768 case BO_GT:
1769 case BO_LE:
1770 case BO_GE:
1771 case BO_EQ:
1772 case BO_NE:
1773 case BO_Cmp:
1774 case BO_And:
1775 case BO_Xor:
1776 case BO_Or:
1777 case BO_LAnd:
1778 case BO_LOr:
1779 case BO_Assign:
1780 case BO_Comma:
1781 llvm_unreachable("Not valid compound assignment operators");
1782 }
1783 llvm_unreachable("Unhandled compound assignment operator");
1784}
1785
1786/// Emit the computation of the specified expression of scalar type.
1788 bool ignoreResultAssign) {
1789 assert(e && hasScalarEvaluationKind(e->getType()) &&
1790 "Invalid scalar expression to emit");
1791
1792 return ScalarExprEmitter(*this, builder, ignoreResultAssign)
1793 .Visit(const_cast<Expr *>(e));
1794}
1795
1797 QualType promotionType) {
1798 if (!promotionType.isNull())
1799 return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);
1800 return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1801}
1802
1803[[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {
1804 // If a null pointer expression's type is the C++0x nullptr_t and
1805 // the expression is not a simple literal, it must be evaluated
1806 // for its potential side effects.
1808 return false;
1809 return e->getType()->isNullPtrType();
1810}
1811
1812/// If \p e is a widened promoted integer, get its base (unpromoted) type.
1813static std::optional<QualType>
1814getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {
1815 const Expr *base = e->IgnoreImpCasts();
1816 if (e == base)
1817 return std::nullopt;
1818
1819 QualType baseTy = base->getType();
1820 if (!astContext.isPromotableIntegerType(baseTy) ||
1821 astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))
1822 return std::nullopt;
1823
1824 return baseTy;
1825}
1826
1827/// Check if \p e is a widened promoted integer.
1828[[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,
1829 const Expr *e) {
1830 return getUnwidenedIntegerType(astContext, e).has_value();
1831}
1832
1833/// Check if we can skip the overflow check for \p Op.
1834[[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,
1835 const BinOpInfo &op) {
1836 assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1837 "Expected a unary or binary operator");
1838
1839 // If the binop has constant inputs and we can prove there is no overflow,
1840 // we can elide the overflow check.
1841 if (!op.mayHaveIntegerOverflow())
1842 return true;
1843
1844 // If a unary op has a widened operand, the op cannot overflow.
1845 if (const auto *uo = dyn_cast<UnaryOperator>(op.e))
1846 return !uo->canOverflow();
1847
1848 // We usually don't need overflow checks for binops with widened operands.
1849 // Multiplication with promoted unsigned operands is a special case.
1850 const auto *bo = cast<BinaryOperator>(op.e);
1851 std::optional<QualType> optionalLHSTy =
1852 getUnwidenedIntegerType(astContext, bo->getLHS());
1853 if (!optionalLHSTy)
1854 return false;
1855
1856 std::optional<QualType> optionalRHSTy =
1857 getUnwidenedIntegerType(astContext, bo->getRHS());
1858 if (!optionalRHSTy)
1859 return false;
1860
1861 QualType lhsTy = *optionalLHSTy;
1862 QualType rhsTy = *optionalRHSTy;
1863
1864 // This is the simple case: binops without unsigned multiplication, and with
1865 // widened operands. No overflow check is needed here.
1866 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1867 !lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())
1868 return true;
1869
1870 // For unsigned multiplication the overflow check can be elided if either one
1871 // of the unpromoted types are less than half the size of the promoted type.
1872 unsigned promotedSize = astContext.getTypeSize(op.e->getType());
1873 return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||
1874 (2 * astContext.getTypeSize(rhsTy)) < promotedSize;
1875}
1876
1877/// Emit pointer + index arithmetic.
1879 const BinOpInfo &op,
1880 bool isSubtraction) {
1881 // Must have binary (not unary) expr here. Unary pointer
1882 // increment/decrement doesn't use this path.
1884
1885 mlir::Value pointer = op.lhs;
1886 Expr *pointerOperand = expr->getLHS();
1887 mlir::Value index = op.rhs;
1888 Expr *indexOperand = expr->getRHS();
1889
1890 // In the case of subtraction, the FE has ensured that the LHS is always the
1891 // pointer. However, addition can have the pointer on either side. We will
1892 // always have a pointer operand and an integer operand, so if the LHS wasn't
1893 // a pointer, we need to swap our values.
1894 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1895 std::swap(pointer, index);
1896 std::swap(pointerOperand, indexOperand);
1897 }
1898 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1899 "Need a pointer operand");
1900 assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");
1901
1902 // Some versions of glibc and gcc use idioms (particularly in their malloc
1903 // routines) that add a pointer-sized integer (known to be a pointer value)
1904 // to a null pointer in order to cast the value back to an integer or as
1905 // part of a pointer alignment algorithm. This is undefined behavior, but
1906 // we'd like to be able to compile programs that use it.
1907 //
1908 // Normally, we'd generate a GEP with a null-pointer base here in response
1909 // to that code, but it's also UB to dereference a pointer created that
1910 // way. Instead (as an acknowledged hack to tolerate the idiom) we will
1911 // generate a direct cast of the integer value to a pointer.
1912 //
1913 // The idiom (p = nullptr + N) is not met if any of the following are true:
1914 //
1915 // The operation is subtraction.
1916 // The index is not pointer-sized.
1917 // The pointer type is not byte-sized.
1918 //
1920 cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))
1921 return cgf.getBuilder().createIntToPtr(index, pointer.getType());
1922
1923 // Differently from LLVM codegen, ABI bits for index sizes is handled during
1924 // LLVM lowering.
1925
1926 // If this is subtraction, negate the index.
1927 if (isSubtraction)
1928 index = cgf.getBuilder().createNeg(cgf.getLoc(op.e->getExprLoc()), index);
1929
1931
1932 const PointerType *pointerType =
1933 pointerOperand->getType()->getAs<PointerType>();
1934 if (!pointerType) {
1935 cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");
1936 return nullptr;
1937 }
1938
1939 QualType elementType = pointerType->getPointeeType();
1940 if (const VariableArrayType *vla =
1941 cgf.getContext().getAsVariableArrayType(elementType)) {
1942 mlir::Value numElements = cgf.getVLASize(vla).numElts;
1943 mlir::Location loc = cgf.getLoc(op.e->getExprLoc());
1944 index = cgf.getBuilder().createCast(cir::CastKind::integral, index,
1945 numElements.getType());
1946 // GEP indexes are signed, and scaling an index isn't permitted to
1947 // signed-overflow, so we use the same semantics for our explicit
1948 // multiply. We suppress this if overflow is not undefined behavior.
1949 cir::OverflowBehavior overflowBehavior =
1950 cgf.getLangOpts().PointerOverflowDefined
1953 index =
1954 cgf.getBuilder().createMul(loc, index, numElements, overflowBehavior);
1956 return cir::PtrStrideOp::create(cgf.getBuilder(), loc, pointer.getType(),
1957 pointer, index);
1958 }
1959
1961 return cir::PtrStrideOp::create(cgf.getBuilder(),
1962 cgf.getLoc(op.e->getExprLoc()),
1963 pointer.getType(), pointer, index);
1964}
1965
1966static bool isIntegerVectorBinOp(mlir::Type ty) {
1967 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1968 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1969}
1970
1971// Construct a cir.fmuladd op to represent a fused mul-add of `mulOp` and
1972// `addend`. Use negMul and negAdd to negate the first operand of the mul or
1973// the addend respectively. This allows fmuladd to represent a*b-c, or c-a*b.
1974// Patterns in LLVM should catch the negated forms and translate them to
1975// efficient operations.
1976static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp,
1977 mlir::Value addend, CIRGenBuilderTy &builder,
1978 bool negMul, bool negAdd) {
1979 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
1980 mlir::Value mulOp0 = mulOp.getLhs();
1981 mlir::Value mulOp1 = mulOp.getRhs();
1982 if (negMul)
1983 mulOp0 = builder.createFNeg(loc, mulOp0);
1984 if (negAdd)
1985 addend = builder.createFNeg(loc, addend);
1986
1987 // Carry the mul's fenv attribute so a constrained fmul yields a constrained
1988 // fmuladd; the builder is under the add's FP options, not the mul's.
1989 mlir::Value fmuladd =
1990 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
1991 addend, mulOp.getFenvAttr());
1992 mulOp.erase();
1993 return fmuladd;
1994}
1995
1996// Check whether it would be legal to emit a cir.fmuladd op to represent op
1997// and if so, build it.
1998//
1999// Checks that (a) the operation is fusable, and (b) -ffp-contract=on.
2000// Does NOT check the type of the operation - it's assumed that this function
2001// will be called from contexts where it's known that the type is contractable.
2002static mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op,
2003 CIRGenBuilderTy &builder,
2004 bool isSub = false) {
2005 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2006 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2007 "Only fadd/fsub can be the root of an fmuladd.");
2008
2009 // Check whether this op is fusable, i.e. -ffp-contract=on. -ffp-contract=fast
2010 // needs fast-math flags on the fmul/fadd, which CIR does not model yet, so it
2011 // fuses nowhere for now.
2013 if (!op.fpFeatures.allowFPContractWithinStatement())
2014 return nullptr;
2015
2016 mlir::Value lhs = op.lhs;
2017 mlir::Value rhs = op.rhs;
2018
2019 // Peek through fneg to look for fmul. Make sure the fneg has no other users,
2020 // and that it is the only use of its operand.
2021 bool negLHS = false;
2022 if (auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2023 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2024 lhs = lhsNeg.getInput();
2025 negLHS = true;
2026 }
2027 }
2028
2029 bool negRHS = false;
2030 if (auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2031 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2032 rhs = rhsNeg.getInput();
2033 negRHS = true;
2034 }
2035 }
2036
2037 // We have a potentially fusable op. Look for a mul on one of the operands.
2038 // Also make sure that the mul result isn't used directly. In that case,
2039 // there's no point creating a muladd operation.
2040 if (auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2041 if (lhsMul.getResult().use_empty() || negLHS) {
2042 // If we looked through fneg, erase it.
2043 if (negLHS)
2044 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2045 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2046 }
2047 }
2048 if (auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2049 if (rhsMul.getResult().use_empty() || negRHS) {
2050 // If we looked through fneg, erase it.
2051 if (negRHS)
2052 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2053 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS, false);
2054 }
2055 }
2056
2057 return nullptr;
2058}
2059
2060mlir::Value ScalarExprEmitter::emitFixedPointIncDec(const UnaryOperator *e,
2061 mlir::Value value,
2062 QualType type) {
2063 // Fixed-point types are tricky. In some cases, it isn't possible to
2064 // represent a 1 or a -1 in the type at all. Piggyback off of
2065 // EmitFixedPointBinOp to avoid having to reimplement saturation.
2066 BinOpInfo info;
2067 info.loc = e->getSourceRange();
2068 info.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
2069 info.e = e;
2070 info.compType = info.fullType = e->getType();
2071 info.opcode = e->isIncrementOp() ? BO_Add : BO_Sub;
2072 info.lhs = value;
2073 info.rhs = builder.getConstInt(cgf.getLoc(info.loc), value.getType(), 1);
2074 // If the type is signed, it's better to represent this as +(-1) or -(-1),
2075 // since -1 is guaranteed to be representable.
2076 // FIXME(cir): This is a carry-over from Classic codegen, we should probably
2077 // figure out if ++ -> -(-1) and -- -> +(-1) is REALLY what we want? For now
2078 // we are just doing what classic does here.
2079 if (type->isSignedFixedPointType()) {
2080 info.opcode = e->isIncrementOp() ? BO_Sub : BO_Add;
2081 info.rhs = builder.createNeg(cgf.getLoc(info.loc), info.rhs);
2082 }
2083 // Now, convert from our invented integer literal to the type of the unary
2084 // op. This will upscale and saturate if necessary. This value can become
2085 // undef in some cases.
2086 CIRGenFixedPointBuilder fpbuilder(builder, cgf.getLoc(info.loc));
2087 auto dstSema = cgf.getContext().getFixedPointSemantics(info.fullType);
2088 info.rhs =
2089 fpbuilder.createIntegerToFixed(info.rhs, /*srcIsSigned=*/true, dstSema);
2090 return emitFixedPointBinOp(info);
2091}
2092
2093mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2094 QualType srcTy,
2095 QualType dstTy,
2096 mlir::Location loc) {
2097 assert(srcTy->isFixedPointType() || dstTy->isFixedPointType());
2098
2099 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2100 mlir::Value result;
2101 if (srcTy->isRealFloatingType()) {
2102 assert(dstTy->isFixedPointType());
2103 result = fpBuilder.createFloatingToFixed(
2104 src, cgf.getContext().getFixedPointSemantics(dstTy));
2105 } else if (dstTy->isRealFloatingType()) {
2106 assert(srcTy->isFixedPointType());
2107 result = fpBuilder.createFixedToFloating(
2108 src, cgf.getContext().getFixedPointSemantics(srcTy),
2109 cgf.convertType(dstTy));
2110 } else {
2111 llvm::FixedPointSemantics srcFPSema =
2113 llvm::FixedPointSemantics dstFPSema =
2115
2116 if (dstTy->isIntegerType())
2117 result = fpBuilder.createFixedToInteger(
2118 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2119 else if (srcTy->isIntegerType())
2120 result =
2121 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2122 else {
2123 assert(srcTy->isFixedPointType() && dstTy->isFixedPointType());
2124 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2125 }
2126 }
2127 return result;
2128}
2129
2130mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {
2131 const mlir::Location loc = cgf.getLoc(ops.loc);
2132 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2133 ops.compType->isSignedIntegerOrEnumerationType()) {
2134 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2135 case LangOptions::SOB_Defined:
2136 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2137 return builder.createMul(loc, ops.lhs, ops.rhs);
2138 [[fallthrough]];
2139 case LangOptions::SOB_Undefined:
2140 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2141 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
2142 [[fallthrough]];
2143 case LangOptions::SOB_Trapping:
2144 if (canElideOverflowCheck(cgf.getContext(), ops))
2145 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
2146 cgf.cgm.errorNYI("sanitizers");
2147 }
2148 }
2149 if (ops.fullType->isConstantMatrixType()) {
2151 cgf.cgm.errorNYI("matrix types");
2152 return nullptr;
2153 }
2154 if (ops.compType->isUnsignedIntegerType() &&
2155 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2156 !canElideOverflowCheck(cgf.getContext(), ops))
2157 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2158
2159 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2160 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2161 return builder.createFMul(loc, ops.lhs, ops.rhs);
2162 }
2163
2164 if (ops.isFixedPointOp())
2165 return emitFixedPointBinOp(ops);
2166
2167 return cir::MulOp::create(builder, cgf.getLoc(ops.loc),
2168 cgf.convertType(ops.fullType), ops.lhs, ops.rhs);
2169}
2170mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
2171 const mlir::Location loc = cgf.getLoc(ops.loc);
2172 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2173 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2174 return builder.createFDiv(loc, ops.lhs, ops.rhs);
2175 }
2176
2177 if (ops.isFixedPointOp())
2178 return emitFixedPointBinOp(ops);
2179
2180 return cir::DivOp::create(builder, loc, cgf.convertType(ops.fullType),
2181 ops.lhs, ops.rhs);
2182}
2183mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
2184 const mlir::Location loc = cgf.getLoc(ops.loc);
2185 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2186 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2187 return builder.createFRem(loc, ops.lhs, ops.rhs);
2188 }
2189 return cir::RemOp::create(builder, loc, cgf.convertType(ops.fullType),
2190 ops.lhs, ops.rhs);
2191}
2192
2193mlir::Value ScalarExprEmitter::emitFixedPointBinOp(const BinOpInfo &ops) {
2194 // This is either a binary operation where at least one of the operands is
2195 // a fixed-point type, or a unary operation where the operand is a fixed-point
2196 // type. The result type of a binary operation is determined by
2197 // Sema::handleFixedPointConversions().
2198 QualType resultTy = ops.compType;
2199 QualType lhsTy, rhsTy;
2200 if (const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2201 rhsTy = binOp->getRHS()->getType();
2202 if (const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2203 // For compound assignment, the effective type of the LHS at this point
2204 // is the computation LHS type, not the actual LHS type, and the final
2205 // result type is not the type of the expression but rather the
2206 // computation result type.
2207 lhsTy = cao->getComputationLHSType();
2208 resultTy = cao->getComputationResultType();
2209 } else {
2210 lhsTy = binOp->getLHS()->getType();
2211 }
2212 } else if (const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2213 lhsTy = unOp->getSubExpr()->getType();
2214 rhsTy = unOp->getSubExpr()->getType();
2215 }
2216 ASTContext &ctx = cgf.getContext();
2217 mlir::Value lhs = ops.lhs;
2218 mlir::Value rhs = ops.rhs;
2219
2220 auto lhsFixedSema = ctx.getFixedPointSemantics(lhsTy);
2221 auto rhsFixedSema = ctx.getFixedPointSemantics(rhsTy);
2222 auto resultFixedSema = ctx.getFixedPointSemantics(resultTy);
2223 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2224
2225 // Perform the actual operation.
2226 mlir::Value result;
2227 CIRGenFixedPointBuilder fpbuilder(builder, cgf.getLoc(ops.loc));
2228 switch (ops.opcode) {
2229 case BO_AddAssign:
2230 case BO_Add:
2231 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2232 break;
2233 case BO_SubAssign:
2234 case BO_Sub:
2235 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2236 break;
2237 case BO_MulAssign:
2238 case BO_Mul:
2239 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2240 break;
2241 case BO_DivAssign:
2242 case BO_Div:
2243 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2244 break;
2245 case BO_ShlAssign:
2246 case BO_Shl:
2247 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2248 break;
2249 case BO_ShrAssign:
2250 case BO_Shr:
2251 result = fpbuilder.createShr(lhs, rhs);
2252 break;
2253 case BO_LT:
2254 case BO_GT:
2255 case BO_LE:
2256 case BO_GE:
2257 case BO_EQ:
2258 case BO_NE:
2259 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2260 clangCmpToCIRCmp(ops.opcode));
2261 case BO_Cmp:
2262 case BO_LAnd:
2263 case BO_LOr:
2264 llvm_unreachable("Found unimplemented fixed point binary operation");
2265 case BO_PtrMemD:
2266 case BO_PtrMemI:
2267 case BO_Rem:
2268 case BO_Xor:
2269 case BO_And:
2270 case BO_Or:
2271 case BO_Assign:
2272 case BO_RemAssign:
2273 case BO_AndAssign:
2274 case BO_XorAssign:
2275 case BO_OrAssign:
2276 case BO_Comma:
2277 llvm_unreachable(
2278 "Found unsupported binary operation for fixed point types.");
2279 }
2280
2281 bool isShift = BinaryOperator::isShiftOp(ops.opcode) ||
2283 // Convert to the result type.
2284 return fpbuilder.createFixedToFixed(
2285 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2286}
2287
2288mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
2289 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2290 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2291 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/
2292 false);
2293
2294 const mlir::Location loc = cgf.getLoc(ops.loc);
2295 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2296 ops.compType->isSignedIntegerOrEnumerationType()) {
2297 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2298 case LangOptions::SOB_Defined:
2299 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2300 return builder.createAdd(loc, ops.lhs, ops.rhs);
2301 [[fallthrough]];
2302 case LangOptions::SOB_Undefined:
2303 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2304 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2305 [[fallthrough]];
2306 case LangOptions::SOB_Trapping:
2307 if (canElideOverflowCheck(cgf.getContext(), ops))
2308 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2309 cgf.cgm.errorNYI("sanitizers");
2310 }
2311 }
2312 if (ops.fullType->isConstantMatrixType()) {
2314 cgf.cgm.errorNYI("matrix types");
2315 return nullptr;
2316 }
2317
2318 if (ops.compType->isUnsignedIntegerType() &&
2319 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2320 !canElideOverflowCheck(cgf.getContext(), ops))
2321 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2322
2323 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2324 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2325 // Try to form an fmuladd.
2326 if (mlir::Value fmuladd = tryEmitFMulAdd(loc, ops, builder))
2327 return fmuladd;
2328 return builder.createFAdd(loc, ops.lhs, ops.rhs);
2329 }
2330
2331 if (ops.isFixedPointOp())
2332 return emitFixedPointBinOp(ops);
2333
2334 return builder.createAdd(loc, ops.lhs, ops.rhs);
2335}
2336
2337mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
2338 const mlir::Location loc = cgf.getLoc(ops.loc);
2339 // The LHS is always a pointer if either side is.
2340 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2341 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2342 ops.compType->isSignedIntegerOrEnumerationType()) {
2343 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2344 case LangOptions::SOB_Defined: {
2345 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2346 return builder.createSub(loc, ops.lhs, ops.rhs);
2347 [[fallthrough]];
2348 }
2349 case LangOptions::SOB_Undefined:
2350 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2351 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2352 [[fallthrough]];
2353 case LangOptions::SOB_Trapping:
2354 if (canElideOverflowCheck(cgf.getContext(), ops))
2355 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2356 cgf.cgm.errorNYI("sanitizers");
2357 }
2358 }
2359
2360 if (ops.fullType->isConstantMatrixType()) {
2362 cgf.cgm.errorNYI("matrix types");
2363 return nullptr;
2364 }
2365
2366 if (ops.compType->isUnsignedIntegerType() &&
2367 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2368 !canElideOverflowCheck(cgf.getContext(), ops))
2369 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2370
2371 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2372 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2373 // Try to form an fmuladd.
2374 if (mlir::Value fmuladd =
2375 tryEmitFMulAdd(loc, ops, builder, /*isSub=*/true))
2376 return fmuladd;
2377 return builder.createFSub(loc, ops.lhs, ops.rhs);
2378 }
2379
2380 if (ops.isFixedPointOp())
2381 return emitFixedPointBinOp(ops);
2382
2383 return builder.createSub(loc, ops.lhs, ops.rhs);
2384 }
2385
2386 // If the RHS is not a pointer, then we have normal pointer
2387 // arithmetic.
2388 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2389 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);
2390
2391 // Otherwise, this is a pointer subtraction
2392
2393 // Do the raw subtraction part.
2394 //
2395 // TODO(cir): note for LLVM lowering out of this; when expanding this into
2396 // LLVM we shall take VLA's, division by element size, etc.
2397 //
2398 // See more in `EmitSub` in CGExprScalar.cpp.
2400 return cir::PtrDiffOp::create(builder, cgf.getLoc(ops.loc), cgf.ptrDiffTy,
2401 ops.lhs, ops.rhs);
2402}
2403
2404mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
2405 // TODO: This misses out on the sanitizer check below.
2406 if (ops.isFixedPointOp())
2407 return emitFixedPointBinOp(ops);
2408
2409 // CIR accepts shift between different types, meaning nothing special
2410 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2411 // promote or truncate the RHS to the same size as the LHS.
2412
2413 bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&
2414 ops.compType->hasSignedIntegerRepresentation() &&
2416 !cgf.getLangOpts().CPlusPlus20;
2417 bool sanitizeUnsignedBase =
2418 cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&
2419 ops.compType->hasUnsignedIntegerRepresentation();
2420 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2421 bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);
2422
2423 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2424 if (cgf.getLangOpts().OpenCL)
2425 cgf.cgm.errorNYI("opencl");
2426 else if ((sanitizeBase || sanitizeExponent) &&
2427 mlir::isa<cir::IntType>(ops.lhs.getType()))
2428 cgf.cgm.errorNYI("sanitizers");
2429
2430 return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2431}
2432
2433mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
2434 // TODO: This misses out on the sanitizer check below.
2435 if (ops.isFixedPointOp())
2436 return emitFixedPointBinOp(ops);
2437
2438 // CIR accepts shift between different types, meaning nothing special
2439 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2440 // promote or truncate the RHS to the same size as the LHS.
2441
2442 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2443 if (cgf.getLangOpts().OpenCL)
2444 cgf.cgm.errorNYI("opencl");
2445 else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&
2446 mlir::isa<cir::IntType>(ops.lhs.getType()))
2447 cgf.cgm.errorNYI("sanitizers");
2448
2449 // Note that we don't need to distinguish unsigned treatment at this
2450 // point since it will be handled later by LLVM lowering.
2451 return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2452}
2453
2454mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {
2455 return cir::AndOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2456}
2457mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {
2458 return cir::XorOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2459}
2460mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {
2461 return cir::OrOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2462}
2463
2464// Emit code for an explicit or implicit cast. Implicit
2465// casts have to handle a more broad range of conversions than explicit
2466// casts, as they handle things like function to ptr-to-function decay
2467// etc.
2468mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
2469 Expr *subExpr = ce->getSubExpr();
2470 QualType destTy = ce->getType();
2471 CastKind kind = ce->getCastKind();
2472 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2473
2474 // These cases are generally not written to ignore the result of evaluating
2475 // their sub-expressions, so we clear this now.
2476 ignoreResultAssign = false;
2477
2478 switch (kind) {
2479 case clang::CK_Dependent:
2480 llvm_unreachable("dependent cast kind in CIR gen!");
2481 case clang::CK_BuiltinFnToFnPtr:
2482 llvm_unreachable("builtin functions are handled elsewhere");
2483 case CK_LValueBitCast:
2484 case CK_LValueToRValueBitCast: {
2485 LValue sourceLVal = cgf.emitLValue(subExpr);
2486 Address sourceAddr = sourceLVal.getAddress();
2487
2488 mlir::Type destElemTy = cgf.convertTypeForMem(destTy);
2489 Address destAddr = sourceAddr.withElementType(cgf.getBuilder(), destElemTy);
2490 LValue destLVal = cgf.makeAddrLValue(destAddr, destTy);
2492 return emitLoadOfLValue(destLVal, ce->getExprLoc());
2493 }
2494
2495 case CK_CPointerToObjCPointerCast:
2496 case CK_BlockPointerToObjCPointerCast:
2497 case CK_AnyPointerToBlockPointerCast:
2498 case CK_BitCast: {
2499 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2500 mlir::Type dstTy = cgf.convertType(destTy);
2501
2503
2504 if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
2505 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2506 "sanitizer support");
2507
2508 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2509 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2510 "strict vtable pointers");
2511
2512 // Update heapallocsite metadata when there is an explicit pointer cast.
2514
2515 // If Src is a fixed vector and Dst is a scalable vector, and both have the
2516 // same element type, use the llvm.vector.insert intrinsic to perform the
2517 // bitcast.
2519
2520 // If Src is a scalable vector and Dst is a fixed vector, and both have the
2521 // same element type, use the llvm.vector.extract intrinsic to perform the
2522 // bitcast.
2524
2525 // Perform VLAT <-> VLST bitcast through memory.
2526 // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
2527 // require the element types of the vectors to be the same, we
2528 // need to keep this around for bitcasts between VLAT <-> VLST where
2529 // the element types of the vectors are not the same, until we figure
2530 // out a better way of doing these casts.
2532
2533 return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
2534 src, dstTy);
2535 }
2536 case CK_AddressSpaceConversion: {
2537 Expr::EvalResult result;
2538 if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
2539 result.Val.isNullPointer()) {
2540 // If e has side effect, it is emitted even if its final result is a
2541 // null pointer. In that case, a DCE pass should be able to
2542 // eliminate the useless instructions emitted during translating E.
2543 if (result.HasSideEffects)
2544 Visit(subExpr);
2545 return cgf.cgm.emitNullConstant(destTy,
2546 cgf.getLoc(subExpr->getExprLoc()));
2547 }
2548 return cgf.performAddrSpaceCast(Visit(subExpr), convertType(destTy));
2549 }
2550
2551 case CK_AtomicToNonAtomic:
2552 case CK_NonAtomicToAtomic:
2553 case CK_UserDefinedConversion:
2554 return Visit(const_cast<Expr *>(subExpr));
2555 case CK_NoOp:
2556 return ce->changesVolatileQualification() ? emitLoadOfLValue(ce)
2557 : Visit(subExpr);
2558 case CK_IntegralToPointer: {
2559 mlir::Type destCIRTy = cgf.convertType(destTy);
2560 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2561
2562 // Properly resize by casting to an int of the same size as the pointer.
2563 // Clang's IntegralToPointer includes 'bool' as the source, but in CIR
2564 // 'bool' is not an integral type. So check the source type to get the
2565 // correct CIR conversion.
2566 mlir::Type middleTy = cgf.cgm.getDataLayout().getIntPtrType(destCIRTy);
2567 mlir::Value middleVal = builder.createCast(
2568 subExpr->getType()->isBooleanType() ? cir::CastKind::bool_to_int
2569 : cir::CastKind::integral,
2570 src, middleTy);
2571
2572 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) {
2573 cgf.cgm.errorNYI(subExpr->getSourceRange(),
2574 "IntegralToPointer: strict vtable pointers");
2575 return {};
2576 }
2577
2578 return builder.createIntToPtr(middleVal, destCIRTy);
2579 }
2580
2581 case CK_BaseToDerived: {
2582 const CXXRecordDecl *derivedClassDecl = destTy->getPointeeCXXRecordDecl();
2583 assert(derivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
2584 Address base = cgf.emitPointerWithAlignment(subExpr);
2585 Address derived = cgf.getAddressOfDerivedClass(
2586 cgf.getLoc(ce->getSourceRange()), base, derivedClassDecl, ce->path(),
2588
2589 // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
2590 // performed and the object is not of the derived type.
2592
2593 return cgf.getAsNaturalPointerTo(derived, ce->getType()->getPointeeType());
2594 }
2595 case CK_UncheckedDerivedToBase:
2596 case CK_DerivedToBase: {
2597 // The EmitPointerWithAlignment path does this fine; just discard
2598 // the alignment.
2600 ce->getType()->getPointeeType());
2601 }
2602 case CK_Dynamic: {
2603 Address v = cgf.emitPointerWithAlignment(subExpr);
2604 const auto *dce = cast<CXXDynamicCastExpr>(ce);
2605 return cgf.emitDynamicCast(v, dce);
2606 }
2607 case CK_ArrayToPointerDecay:
2608 return cgf.emitArrayToPointerDecay(subExpr).getPointer();
2609
2610 case CK_NullToPointer: {
2611 if (mustVisitNullValue(subExpr))
2612 cgf.emitIgnoredExpr(subExpr);
2613
2614 // Note that DestTy is used as the MLIR type instead of a custom
2615 // nullptr type.
2616 mlir::Type ty = cgf.convertType(destTy);
2617 return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
2618 }
2619
2620 case CK_NullToMemberPointer: {
2621 if (mustVisitNullValue(subExpr))
2622 cgf.emitIgnoredExpr(subExpr);
2623
2625
2626 const MemberPointerType *mpt = ce->getType()->getAs<MemberPointerType>();
2627 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2628 return cgf.getBuilder().getConstant(
2629 loc, cgf.cgm.emitNullMemberAttr(destTy, mpt));
2630 }
2631
2632 case CK_ReinterpretMemberPointer: {
2633 mlir::Value src = Visit(subExpr);
2634 return builder.createBitcast(cgf.getLoc(subExpr->getExprLoc()), src,
2635 cgf.convertType(destTy));
2636 }
2637 case CK_BaseToDerivedMemberPointer:
2638 case CK_DerivedToBaseMemberPointer: {
2639 mlir::Value src = Visit(subExpr);
2640
2642
2643 QualType derivedTy =
2644 kind == CK_DerivedToBaseMemberPointer ? subExpr->getType() : destTy;
2645 const auto *mpType = derivedTy->castAs<MemberPointerType>();
2646 NestedNameSpecifier qualifier = mpType->getQualifier();
2647 assert(qualifier && "member pointer without class qualifier");
2648 const Type *qualifierType = qualifier.getAsType();
2649 assert(qualifierType && "member pointer qualifier is not a type");
2650 const CXXRecordDecl *derivedClass = qualifierType->getAsCXXRecordDecl();
2651 CharUnits offset =
2652 cgf.cgm.computeNonVirtualBaseClassOffset(derivedClass, ce->path());
2653
2654 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2655 mlir::Type resultTy = cgf.convertType(destTy);
2656 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.getQuantity());
2657
2658 if (subExpr->getType()->isMemberFunctionPointerType()) {
2659 if (kind == CK_BaseToDerivedMemberPointer)
2660 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2661 offsetAttr);
2662 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2663 }
2664
2665 if (kind == CK_BaseToDerivedMemberPointer)
2666 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2667 offsetAttr);
2668 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2669 offsetAttr);
2670 }
2671
2672 case CK_LValueToRValue:
2673 assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
2674 assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
2675 return Visit(const_cast<Expr *>(subExpr));
2676
2677 case CK_IntegralCast: {
2678 ScalarConversionOpts opts;
2679 if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2680 if (!ice->isPartOfExplicitCast())
2681 opts = ScalarConversionOpts(cgf.sanOpts);
2682 }
2683 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2684 ce->getExprLoc(), opts);
2685 }
2686
2687 case CK_FloatingComplexToReal:
2688 case CK_IntegralComplexToReal:
2689 case CK_FloatingComplexToBoolean:
2690 case CK_IntegralComplexToBoolean: {
2691 mlir::Value value = cgf.emitComplexExpr(subExpr);
2692 return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,
2693 kind, destTy);
2694 }
2695
2696 case CK_FloatingRealToComplex:
2697 case CK_FloatingComplexCast:
2698 case CK_IntegralRealToComplex:
2699 case CK_IntegralComplexCast:
2700 case CK_IntegralComplexToFloatingComplex:
2701 case CK_FloatingComplexToIntegralComplex:
2702 llvm_unreachable("scalar cast to non-scalar value");
2703
2704 case CK_PointerToIntegral: {
2705 assert(!destTy->isBooleanType() && "bool should use PointerToBool");
2706 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2707 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2708 "strict vtable pointers");
2709 return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));
2710 }
2711 case CK_ToVoid:
2712 cgf.emitIgnoredExpr(subExpr);
2713 return {};
2714
2715 case CK_FixedPointCast:
2716 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2717 ce->getExprLoc());
2718
2719 case CK_FixedPointToBoolean:
2720 assert(subExpr->getType()->isFixedPointType() &&
2721 "Expected src type to be fixed point type");
2722 assert(destTy->isBooleanType() && "Expected dest type to be boolean type");
2723 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2724 ce->getExprLoc());
2725
2726 case CK_FixedPointToIntegral:
2727 assert(subExpr->getType()->isFixedPointType() &&
2728 "Expected src type to be fixed point type");
2729 assert(destTy->isIntegerType() && "Expected dest type to be an integer");
2730 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2731 ce->getExprLoc());
2732
2733 case CK_IntegralToFixedPoint:
2734 assert(subExpr->getType()->isIntegerType() &&
2735 "Expected src type to be an integer");
2736 assert(destTy->isFixedPointType() &&
2737 "Expected dest type to be fixed point type");
2738 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2739 ce->getExprLoc());
2740
2741 case CK_IntegralToFloating:
2742 case CK_FloatingToIntegral:
2743 case CK_FloatingCast:
2744 case CK_FixedPointToFloating:
2745 case CK_FloatingToFixedPoint: {
2746 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2747 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2748 ce->getExprLoc());
2749 }
2750
2751 case CK_IntegralToBoolean:
2752 return emitIntToBoolConversion(Visit(subExpr),
2753 cgf.getLoc(ce->getSourceRange()));
2754
2755 case CK_PointerToBoolean:
2756 return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());
2757 case CK_FloatingToBoolean:
2758 return emitFloatToBoolConversion(Visit(subExpr),
2759 cgf.getLoc(subExpr->getExprLoc()));
2760 case CK_MemberPointerToBoolean: {
2761 mlir::Value memPtr = Visit(subExpr);
2762 return builder.createCast(cgf.getLoc(ce->getSourceRange()),
2763 cir::CastKind::member_ptr_to_bool, memPtr,
2764 cgf.convertType(destTy));
2765 }
2766
2767 case CK_VectorSplat: {
2768 // Create a vector object and fill all elements with the same scalar value.
2769 assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
2770 return cir::VecSplatOp::create(builder,
2771 cgf.getLoc(subExpr->getSourceRange()),
2772 cgf.convertType(destTy), Visit(subExpr));
2773 }
2774 case CK_FunctionToPointerDecay:
2775 return cgf.emitLValue(subExpr).getPointer();
2776
2777 default:
2778 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2779 "CastExpr: ", ce->getCastKindName());
2780 }
2781 return {};
2782}
2783
2784mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
2786 return emitLoadOfLValue(e);
2787
2788 auto v = cgf.emitCallExpr(e).getValue();
2790 return v;
2791}
2792
2793mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2794 // TODO(cir): The classic codegen calls tryEmitAsConstant() here. Folding
2795 // constants sound like work for MLIR optimizers, but we'll keep an assertion
2796 // for now.
2798 Expr::EvalResult result;
2799 if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {
2800 llvm::APSInt value = result.Val.getInt();
2801 cgf.emitIgnoredExpr(e->getBase());
2802 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2803 // The constant is folded from an APSInt with the source-type's bit width
2804 // (1 for bool), but the AST's expression type is what later consumers of
2805 // this value see. For a bool member we have to emit a !cir.bool constant
2806 // -- otherwise downstream ops (cir.call into a bool parameter, cir.if /
2807 // cir.ternary on the value, ...) would all reject the !cir.int<u, 1> the
2808 // raw APSInt would produce.
2809 if (e->getType()->isBooleanType())
2810 return builder.getBool(value.getBoolValue(), loc);
2811 return builder.getConstInt(loc, value);
2812 }
2813 return emitLoadOfLValue(e);
2814}
2815
2816mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2817 const unsigned numInitElements = e->getNumInits();
2818
2819 [[maybe_unused]] const bool ignore = std::exchange(ignoreResultAssign, false);
2820 assert((ignore == false ||
2821 (numInitElements == 0 && e->getType()->isVoidType())) &&
2822 "init list ignored");
2823
2824 if (e->hadArrayRangeDesignator()) {
2825 cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
2826 return {};
2827 }
2828
2829 if (e->getType()->isVectorType()) {
2830 const auto vectorType =
2831 mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
2832
2833 SmallVector<mlir::Value, 16> elements;
2834 for (Expr *init : e->inits()) {
2835 elements.push_back(Visit(init));
2836 }
2837
2838 // Zero-initialize any remaining values.
2839 if (numInitElements < vectorType.getSize()) {
2840 const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
2841 vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
2842 std::fill_n(std::back_inserter(elements),
2843 vectorType.getSize() - numInitElements, zeroValue);
2844 }
2845
2846 return cir::VecCreateOp::create(cgf.getBuilder(),
2847 cgf.getLoc(e->getSourceRange()), vectorType,
2848 elements);
2849 }
2850
2851 // C++11 value-initialization for the scalar.
2852 if (numInitElements == 0)
2853 return emitNullValue(e->getType(), cgf.getLoc(e->getExprLoc()));
2854
2855 return Visit(e->getInit(0));
2856}
2857
2858mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
2859 QualType srcTy, QualType dstTy,
2860 SourceLocation loc) {
2863 "Invalid scalar expression to emit");
2864 return ScalarExprEmitter(*this, builder)
2865 .emitScalarConversion(src, srcTy, dstTy, loc);
2866}
2867
2869 QualType srcTy,
2870 QualType dstTy,
2871 SourceLocation loc) {
2872 assert(srcTy->isAnyComplexType() && hasScalarEvaluationKind(dstTy) &&
2873 "Invalid complex -> scalar conversion");
2874
2875 QualType complexElemTy = srcTy->castAs<ComplexType>()->getElementType();
2876 if (dstTy->isBooleanType()) {
2877 auto kind = complexElemTy->isFloatingType()
2878 ? cir::CastKind::float_complex_to_bool
2879 : cir::CastKind::int_complex_to_bool;
2880 return builder.createCast(getLoc(loc), kind, src, convertType(dstTy));
2881 }
2882
2883 auto kind = complexElemTy->isFloatingType()
2884 ? cir::CastKind::float_complex_to_real
2885 : cir::CastKind::int_complex_to_real;
2886 mlir::Value real =
2887 builder.createCast(getLoc(loc), kind, src, convertType(complexElemTy));
2888 return emitScalarConversion(real, complexElemTy, dstTy, loc);
2889}
2890
2891mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
2892 // Perform vector logical not on comparison with zero vector.
2893 if (e->getType()->isVectorType() &&
2894 e->getType()->castAs<VectorType>()->getVectorKind() ==
2896 mlir::Value oper = Visit(e->getSubExpr());
2897 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2898 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2899 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2900 return builder.createVecCompare(loc, cir::CmpOpKind::eq, oper, zeroVec);
2901 }
2902
2903 // Compare operand to zero.
2904 mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());
2905
2906 // Invert value.
2907 boolVal = builder.createNot(boolVal);
2908
2909 // ZExt result to the expr type.
2910 return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
2911}
2912
2913mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {
2914 // Try folding the offsetof to a constant.
2915 Expr::EvalResult evalResult;
2916 if (e->EvaluateAsInt(evalResult, cgf.getContext())) {
2917 mlir::Type type = cgf.convertType(e->getType());
2918 llvm::APSInt value = evalResult.Val.getInt();
2919 return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);
2920 }
2921
2923 e->getSourceRange(),
2924 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2925 return {};
2926}
2927
2928mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
2929 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
2930 mlir::Value result = VisitRealImag(e, promotionTy);
2931 if (result && !promotionTy.isNull())
2932 result = emitUnPromotedValue(result, e->getType());
2933 return result;
2934}
2935
2936mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {
2937 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
2938 mlir::Value result = VisitRealImag(e, promotionTy);
2939 if (result && !promotionTy.isNull())
2940 result = emitUnPromotedValue(result, e->getType());
2941 return result;
2942}
2943
2944mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
2945 QualType promotionTy) {
2946 assert(
2947 (e->getOpcode() == clang::UO_Real || e->getOpcode() == clang::UO_Imag) &&
2948 "Invalid UnaryOp kind for ComplexType Real or Imag");
2949
2950 Expr *op = e->getSubExpr();
2951 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2952 if (op->getType()->isAnyComplexType()) {
2953 // If it's an l-value, load through the appropriate subobject l-value.
2954 // Note that we have to ask `e` because `op` might be an l-value that
2955 // this won't work for, e.g. an Obj-C property
2956 mlir::Value complex = cgf.emitComplexExpr(op);
2957 if (e->isGLValue() && !promotionTy.isNull()) {
2958 promotionTy = promotionTy->isAnyComplexType()
2959 ? promotionTy
2960 : cgf.getContext().getComplexType(promotionTy);
2961 complex = cgf.emitPromotedValue(complex, promotionTy);
2962 }
2963
2964 return e->getOpcode() == clang::UO_Real
2965 ? builder.createComplexReal(loc, complex)
2966 : builder.createComplexImag(loc, complex);
2967 }
2968
2969 if (e->getOpcode() == UO_Real) {
2970 mlir::Value operand = promotionTy.isNull()
2971 ? Visit(op)
2972 : cgf.emitPromotedScalarExpr(op, promotionTy);
2973 return builder.createComplexReal(loc, operand);
2974 }
2975
2976 // __imag on a scalar returns zero. Emit the subexpr to ensure side
2977 // effects are evaluated, but not the actual value.
2978 mlir::Value operand;
2979 if (op->isGLValue()) {
2980 operand = cgf.emitLValue(op).getPointer();
2981 operand = cir::LoadOp::create(builder, loc, operand);
2982 } else if (!promotionTy.isNull()) {
2983 operand = cgf.emitPromotedScalarExpr(op, promotionTy);
2984 } else {
2985 operand = cgf.emitScalarExpr(op);
2986 }
2987 return builder.createComplexImag(loc, operand);
2988}
2989
2990/// Return the size or alignment of the type of argument of the sizeof
2991/// expression as an integer.
2992mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2993 const UnaryExprOrTypeTraitExpr *e) {
2994 const QualType typeToSize = e->getTypeOfArgument();
2995 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
2996 if (auto kind = e->getKind();
2997 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
2998 if (const VariableArrayType *vat =
2999 cgf.getContext().getAsVariableArrayType(typeToSize)) {
3000 // For _Countof, we only want to evaluate if the extent is actually
3001 // variable as opposed to a multi-dimensional array whose extent is
3002 // constant but whose element type is variable.
3003 bool evaluateExtent = true;
3004 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3005 evaluateExtent =
3006 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.getContext());
3007 }
3008
3009 if (evaluateExtent) {
3010 if (e->isArgumentType()) {
3011 // sizeof(type) - make sure to emit the VLA size.
3012 cgf.emitVariablyModifiedType(typeToSize);
3013 } else {
3014 // C99 6.5.3.4p2: If the argument is an expression of type
3015 // VLA, it is evaluated.
3017 }
3018
3019 // For _Countof, we just want to return the size of a single dimension.
3020 if (kind == UETT_CountOf)
3021 return cgf.getVLAElements1D(vat).numElts;
3022
3023 // For sizeof and __datasizeof, we need to scale the number of elements
3024 // by the size of the array element type.
3025 CIRGenFunction::VlaSizePair vlaSize = cgf.getVLASize(vat);
3026 mlir::Value numElts = vlaSize.numElts;
3027
3028 // Scale the number of non-VLA elements by the non-VLA element size.
3029 CharUnits eltSize = cgf.getContext().getTypeSizeInChars(vlaSize.type);
3030 if (!eltSize.isOne()) {
3031 mlir::Location loc = cgf.getLoc(e->getSourceRange());
3032 mlir::Value eltSizeValue =
3033 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
3034 cgf.cgm.getSize(eltSize).getValue());
3035 return builder.createMul(loc, eltSizeValue, numElts,
3037 }
3038
3039 return numElts;
3040 }
3041 }
3042 } else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
3044 cgf.getContext()
3047 .getQuantity();
3048 return builder.getConstantInt(loc, cgf.cgm.sizeTy, alignment);
3049 } else if (e->getKind() == UETT_VectorElements) {
3050 auto vecTy = cast<cir::VectorType>(convertType(e->getTypeOfArgument()));
3051 if (vecTy.getIsScalable()) {
3053 e->getSourceRange(),
3054 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3055 return builder.getConstant(
3056 loc, cir::IntAttr::get(cgf.cgm.sizeTy,
3058 }
3059
3060 return builder.getConstant(
3061 loc, cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getSize()));
3062 }
3063
3064 // The result type is size_t (target-dependent width); use it so the IntAttr
3065 // width matches the APInt from EvaluateKnownConstInt.
3066 return builder.getConstant(
3067 loc, cir::IntAttr::get(cgf.cgm.sizeTy,
3069}
3070
3071/// Return true if the specified expression is cheap enough and side-effect-free
3072/// enough to evaluate unconditionally instead of conditionally. This is used
3073/// to convert control flow into selects in some cases.
3074/// TODO(cir): can be shared with LLVM codegen.
3076 CIRGenFunction &cgf) {
3077 // Anything that is an integer or floating point constant is fine.
3078 return e->IgnoreParens()->isEvaluatable(cgf.getContext());
3079
3080 // Even non-volatile automatic variables can't be evaluated unconditionally.
3081 // Referencing a thread_local may cause non-trivial initialization work to
3082 // occur. If we're inside a lambda and one of the variables is from the scope
3083 // outside the lambda, that function may have returned already. Reading its
3084 // locals is a bad idea. Also, these reads may introduce races there didn't
3085 // exist in the source-level program.
3086}
3087
3088mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3089 const AbstractConditionalOperator *e) {
3090 CIRGenBuilderTy &builder = cgf.getBuilder();
3091 mlir::Location loc = cgf.getLoc(e->getSourceRange());
3092 ignoreResultAssign = false;
3093
3094 // Bind the common expression if necessary.
3095 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3096
3097 Expr *condExpr = e->getCond();
3098 Expr *lhsExpr = e->getTrueExpr();
3099 Expr *rhsExpr = e->getFalseExpr();
3100
3101 // If the condition constant folds and can be elided, try to avoid emitting
3102 // the condition and the dead arm.
3103 bool condExprBool;
3104 if (cgf.constantFoldsToBool(condExpr, condExprBool)) {
3105 Expr *live = lhsExpr, *dead = rhsExpr;
3106 if (!condExprBool)
3107 std::swap(live, dead);
3108
3109 // If the dead side doesn't have labels we need, just emit the Live part.
3110 if (!cgf.containsLabel(dead)) {
3111 if (condExprBool)
3113 mlir::Value result = Visit(live);
3114
3115 // If the live part is a throw expression, it acts like it has a void
3116 // type, so evaluating it returns a null Value. However, a conditional
3117 // with non-void type must return a non-null Value.
3118 if (!result && !e->getType()->isVoidType()) {
3119 result = builder.getConstant(
3120 loc, cir::PoisonAttr::get(builder.getContext(),
3121 cgf.convertType(e->getType())));
3122 }
3123
3124 return result;
3125 }
3126 }
3127
3128 QualType condType = condExpr->getType();
3129
3130 // OpenCL: If the condition is a vector, we can treat this condition like
3131 // the select function.
3132 if (cgf.getLangOpts().OpenCL &&
3133 (condType->isVectorType() || condType->isExtVectorType())) {
3135
3136 mlir::Value condValue = cgf.emitScalarExpr(condExpr);
3137 mlir::Value lhsValue = Visit(lhsExpr);
3138 mlir::Value rhsValue = Visit(rhsExpr);
3139
3140 mlir::Type vecTy = convertType(condType);
3141 mlir::Value zeroVec = builder.getNullValue(vecTy, loc);
3142 auto testMSB = cir::VecCmpOp::create(
3143 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3144 mlir::Value tmp = builder.createIntCast(testMSB, vecTy);
3145 mlir::Value tmp2 = builder.createNot(tmp);
3146
3147 // Cast float to int to perform ANDs if necessary.
3148 mlir::Value rhsTmp = rhsValue;
3149 mlir::Value lhsTmp = lhsValue;
3150 bool wasCast = false;
3151 auto rhsVecTy = cast<cir::VectorType>(rhsValue.getType());
3152 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
3153 rhsTmp = builder.createBitcast(rhsValue, tmp2.getType());
3154 lhsTmp = builder.createBitcast(lhsValue, tmp.getType());
3155 wasCast = true;
3156 }
3157
3158 mlir::Value tmp3 = builder.createAnd(loc, rhsTmp, tmp2);
3159 mlir::Value tmp4 = builder.createAnd(loc, lhsTmp, tmp);
3160 mlir::Value tmp5 = builder.createOr(loc, tmp3, tmp4);
3161 if (wasCast)
3162 tmp5 = builder.createBitcast(tmp5, rhsValue.getType());
3163 return tmp5;
3164 }
3165
3166 if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {
3167 if (!condType->isVectorType()) {
3169 cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");
3170 return {};
3171 }
3172
3173 mlir::Value condValue = Visit(condExpr);
3174 mlir::Value lhsValue = Visit(lhsExpr);
3175 mlir::Value rhsValue = Visit(rhsExpr);
3176 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3177 rhsValue);
3178 }
3179
3180 // If this is a really simple expression (like x ? 4 : 5), emit this as a
3181 // select instead of as control flow. We can only do this if it is cheap
3182 // and safe to evaluate the LHS and RHS unconditionally.
3183 if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&
3185 bool lhsIsVoid = false;
3186 mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
3188
3189 mlir::Value lhs = Visit(lhsExpr);
3190 if (!lhs) {
3191 lhs = builder.getNullValue(cgf.voidTy, loc);
3192 lhsIsVoid = true;
3193 }
3194
3195 mlir::Value rhs = Visit(rhsExpr);
3196 if (lhsIsVoid) {
3197 assert(!rhs && "lhs and rhs types must match");
3198 rhs = builder.getNullValue(cgf.voidTy, loc);
3199 }
3200
3201 return builder.createSelect(loc, condV, lhs, rhs);
3202 }
3203
3204 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);
3205 CIRGenFunction::ConditionalEvaluation eval(cgf);
3206
3207 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {
3208 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3210
3211 mlir::Value branch;
3212 {
3213 // Emit any cleanups that were needed on this branch so we can spill
3214 // and reload the return value.
3215 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3217 eval.beginEvaluation();
3218 branch = Visit(expr);
3219 eval.endEvaluation();
3220 branchCleanups.forceCleanup({&branch});
3221 }
3222
3223 if (branch)
3224 cir::YieldOp::create(b, loc, branch);
3225 };
3226
3227 cir::TernaryOp ternary = cir::TernaryOp::create(
3228 builder, loc, condV,
3229 /*trueBuilder=*/
3230 [&](mlir::OpBuilder &b, mlir::Location loc) {
3231 emitBranch(b, loc, lhsExpr);
3232 },
3233 /*falseBuilder=*/
3234 [&](mlir::OpBuilder &b, mlir::Location loc) {
3235 emitBranch(b, loc, rhsExpr);
3236 });
3237
3238 // Only a void arm can be left unterminated (a noreturn arm already ends
3239 // in cir.unreachable); close it with an empty cir.yield.
3240 for (mlir::Region *region :
3241 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3242 mlir::Block &lastBlock = region->back();
3243 if (lastBlock.empty() ||
3244 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3245 mlir::OpBuilder::InsertionGuard guard(builder);
3246 builder.setInsertionPointToEnd(&lastBlock);
3247 cir::YieldOp::create(builder, loc);
3248 }
3249 }
3250
3251 return ternary.getResult();
3252}
3253
3255 LValue lv) {
3256 return ScalarExprEmitter(*this, builder).emitScalarPrePostIncDec(e, lv);
3257}
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
#define HANDLE_BINOP(OP)
static bool mustVisitNullValue(const Expr *e)
#define COMPOUND_OP(Op)
#define HANDLEBINOP(OP)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op, CIRGenBuilderTy &builder, bool isSub=false)
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp, mlir::Value addend, CIRGenBuilderTy &builder, bool negMul, bool negAdd)
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
#define VISITCOMP(CODE)
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
APSInt & getInt()
Definition APValue.h:511
bool isNullPointer() const
Definition APValue.cpp:1054
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
CanQualType FloatTy
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4575
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4581
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4587
LabelDecl * getLabel() const
Definition Expr.h:4617
uint64_t getValue() const
Definition ExprCXX.h:3058
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
Definition Expr.h:6802
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
SourceLocation getExprLoc() const
Definition Expr.h:4123
bool isShiftOp() const
Definition Expr.h:4171
Expr * getRHS() const
Definition Expr.h:4134
bool isShiftAssignOp() const
Definition Expr.h:4240
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:4295
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
Definition Expr.cpp:2236
Opcode getOpcode() const
Definition Expr.h:4127
BinaryOperatorKind Opcode
Definition Expr.h:4087
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
bool getValue() const
Definition ExprCXX.h:744
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1138
bool getValue() const
Definition ExprCXX.h:4385
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:308
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
CastKind getCastKind() const
Definition Expr.h:3764
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3807
bool changesVolatileQualification() const
Return.
Definition Expr.h:3854
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1981
Expr * getSubExpr()
Definition Expr.h:3770
int64_t QuantityType
Definition CharUnits.h:40
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
bool isOne() const
isOne - Test whether the quantity equals one.
Definition CharUnits.h:125
unsigned getValue() const
Definition Expr.h:1649
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4928
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3355
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4344
QualType getComputationLHSType() const
Definition Expr.h:4378
QualType getComputationResultType() const
Definition Expr.h:4381
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
Definition Expr.h:4853
ChildElementIter< false > begin()
Definition Expr.h:5285
size_t getDataElementCount() const
Definition Expr.h:5201
This represents one expression.
Definition Expr.h:113
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition Expr.h:288
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:695
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3103
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
bool allowFPContractWithinStatement() const
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
Definition Expr.h:1595
llvm::APFloat getValue() const
Definition Expr.h:1686
const Expr * getSubExpr() const
Definition Expr.h:1082
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6518
unsigned getNumInits() const
Definition Expr.h:5385
bool hadArrayRangeDesignator() const
Definition Expr.h:5533
const Expr * getInit(unsigned Init) const
Definition Expr.h:5407
ArrayRef< Expr * > inits() const
Definition Expr.h:5405
bool isSignedOverflowDefined() const
Expr * getBase() const
Definition Expr.h:3485
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3603
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:247
SourceRange getSourceRange() const
Definition ExprObjC.h:1754
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:189
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:414
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2571
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:1228
Expr * getSelectedExpr() const
Definition ExprCXX.h:4692
const Expr * getSubExpr() const
Definition Expr.h:2243
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3408
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8501
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1454
QualType getCanonicalType() const
Definition TypeBase.h:8553
bool UseExcessPrecision(const ASTContext &Ctx)
Definition Type.cpp:1679
bool isCanonical() const
Definition TypeBase.h:8558
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:362
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:355
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:351
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:365
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:368
bool isSatisfied() const
Whether or not the requires clause is satisfied.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Definition Expr.h:4720
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
Definition Expr.h:4726
unsigned getPackLength() const
Retrieve the length of the parameter pack.
Definition ExprCXX.h:4568
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
Definition Expr.cpp:2313
SourceLocation getLocation() const
Definition Expr.h:5114
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
Definition Expr.h:4656
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
const char * getStmtClassName() const
Definition Stmt.cpp:86
bool getBoolValue() const
Definition ExprCXX.h:2961
const APValue & getAPValue() const
Definition ExprCXX.h:2966
bool isStoredAsBoolean() const
Definition ExprCXX.h:2953
bool isVoidType() const
Definition TypeBase.h:9110
bool isBooleanType() const
Definition TypeBase.h:9247
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2319
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2296
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantMatrixType() const
Definition TypeBase.h:8905
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9154
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9404
bool isReferenceType() const
Definition TypeBase.h:8762
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition Type.cpp:1984
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
Definition Type.cpp:2733
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2408
bool isExtVectorType() const
Definition TypeBase.h:8881
bool isExtVectorBoolType() const
Definition TypeBase.h:8885
bool isAnyComplexType() const
Definition TypeBase.h:8873
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition TypeBase.h:9170
bool isHalfType() const
Definition TypeBase.h:9114
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2340
bool isMatrixType() const
Definition TypeBase.h:8901
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8823
bool isVectorType() const
Definition TypeBase.h:8877
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2437
bool isFloatingType() const
Definition Type.cpp:2421
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition Type.cpp:2364
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9337
bool isNullPtrType() const
Definition TypeBase.h:9147
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2738
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2701
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
SourceLocation getExprLoc() const
Definition Expr.h:2412
Expr * getSubExpr() const
Definition Expr.h:2329
Opcode getOpcode() const
Definition Expr.h:2324
static bool isIncrementOp(Opcode Op)
Definition Expr.h:2370
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:2444
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2363
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Definition Expr.h:2342
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4080
Represents a GCC generic vector type.
Definition TypeBase.h:4289
VectorKind getVectorKind() const
Definition TypeBase.h:4309
OverflowBehavior
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Definition Utils.h:57
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Type
The name was classified as a type.
Definition Sema.h:558
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
Definition TypeBase.h:4250
U cast(CodeGen::Address addr)
Definition Address.h:327
long int64_t
#define false
Definition stdbool.h:26
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool fastMathFlags()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
bool HasSideEffects
Whether the evaluated expression has side effects.
Definition Expr.h:625
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
Definition Sanitizers.h:174