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