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