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