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