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(loc, 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 mlir::Location loc = cgf.getLoc(e->getExprLoc());
708 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
709 mlir::Value amount = builder.getConstFP(
710 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
711 value = e->isIncrementOp() ? builder.createFAdd(loc, value, amount)
712 : builder.createFSub(loc, value, amount);
713 } else {
714 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
715 return {};
716 }
717 } else if (type->isFixedPointType()) {
718 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fixed point");
719 return {};
720 } else {
721 assert(type->castAs<ObjCObjectPointerType>());
722 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");
723 return {};
724 }
725
726 CIRGenFunction::SourceLocRAIIObject sourceloc{
727 cgf, cgf.getLoc(e->getSourceRange())};
728
729 // Store the updated result through the lvalue
730 if (lv.isBitField())
731 return cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);
732 else
733 cgf.emitStoreThroughLValue(RValue::get(value), lv);
734
735 // If this is a postinc, return the value read from memory, otherwise use
736 // the updated value.
737 return e->isPrefix() ? value : input;
738 }
739
740 mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,
741 mlir::Value inVal) {
742 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
743 case LangOptions::SOB_Defined:
744 return emitIncOrDec(e, inVal, /*nsw=*/false);
745 case LangOptions::SOB_Undefined:
747 return emitIncOrDec(e, inVal, /*nsw=*/true);
748 case LangOptions::SOB_Trapping:
749 if (!e->canOverflow())
750 return emitIncOrDec(e, inVal, /*nsw=*/true);
751 cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
752 return {};
753 }
754 llvm_unreachable("Unexpected signed overflow behavior kind");
755 }
756
757 mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
758 if (llvm::isa<MemberPointerType>(e->getType()))
759 return cgf.cgm.emitMemberPointerConstant(e);
760
761 return cgf.emitLValue(e->getSubExpr()).getPointer();
762 }
763
764 mlir::Value VisitUnaryDeref(const UnaryOperator *e) {
765 if (e->getType()->isVoidType())
766 return Visit(e->getSubExpr()); // the actual value should be unused
767 return emitLoadOfLValue(e);
768 }
769
770 mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
771 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
772 mlir::Value result = VisitUnaryPlus(e, promotionType);
773 if (result && !promotionType.isNull())
774 return emitUnPromotedValue(result, e->getType());
775 return result;
776 }
777
778 mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType) {
779 ignoreResultAssign = false;
780 if (!promotionType.isNull())
781 return cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
782 return Visit(e->getSubExpr());
783 }
784
785 mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
786 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
787 mlir::Value result = VisitUnaryMinus(e, promotionType);
788 if (result && !promotionType.isNull())
789 return emitUnPromotedValue(result, e->getType());
790 return result;
791 }
792
793 mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType) {
794 ignoreResultAssign = false;
795 mlir::Value operand;
796 if (!promotionType.isNull())
797 operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
798 else
799 operand = Visit(e->getSubExpr());
800
801 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
802
803 if (cir::isFPOrVectorOfFPType(operand.getType()))
804 return builder.createOrFold<cir::FNegOp>(loc, operand);
805
806 // TODO(cir): We might have to change this to support overflow trapping.
807 // Classic codegen routes unary minus through emitSub to ensure
808 // that the overflow behavior is handled correctly.
809 bool nsw = e->getType()->isSignedIntegerType() &&
810 cgf.getLangOpts().getSignedOverflowBehavior() !=
811 LangOptions::SOB_Defined;
812
813 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
814 }
815
816 mlir::Value emitIncOrDec(const UnaryOperator *e, mlir::Value input,
817 bool nsw = false) {
818 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
819 return e->isIncrementOp()
820 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
821 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
822 }
823
824 mlir::Value VisitUnaryNot(const UnaryOperator *e) {
825 ignoreResultAssign = false;
826 mlir::Value op = Visit(e->getSubExpr());
827 return builder.createOrFold<cir::NotOp>(
828 cgf.getLoc(e->getSourceRange().getBegin()), op);
829 }
830
831 mlir::Value VisitUnaryLNot(const UnaryOperator *e);
832
833 mlir::Value VisitUnaryReal(const UnaryOperator *e);
834 mlir::Value VisitUnaryImag(const UnaryOperator *e);
835 mlir::Value VisitRealImag(const UnaryOperator *e,
836 QualType promotionType = QualType());
837
838 mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
839 return Visit(e->getSubExpr());
840 }
841
842 // C++
843 mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e) {
844 cgf.cgm.errorNYI(e->getSourceRange(),
845 "ScalarExprEmitter: materialize temporary");
846 return {};
847 }
848 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
849 ASTContext &ctx = cgf.getContext();
850 APValue evaluated =
851 e->EvaluateInContext(ctx, cgf.curSourceLocExprScope.getDefaultExpr());
852 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
853 e->getLocation(), evaluated, e->getType());
854 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
855 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
856 typedAttr);
857 }
858 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
859 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
860 return Visit(dae->getExpr());
861 }
862 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
863 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
864 return Visit(die->getExpr());
865 }
866
867 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
868
869 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
870 mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
871 return cgf.emitCXXNewExpr(e);
872 }
873 mlir::Value VisitCXXDeleteExpr(const CXXDeleteExpr *e) {
874 cgf.emitCXXDeleteExpr(e);
875 return {};
876 }
877 mlir::Value VisitTypeTraitExpr(const TypeTraitExpr *e) {
878 // We diverge slightly from classic codegen here because CIR has stricter
879 // typing. In LLVM IR, constant folding covers up some potential type
880 // mismatches such as bool-to-int conversions that would fail the verifier
881 // in CIR. To make things work, we need to be sure we only emit a bool value
882 // if the expression type is bool.
883 mlir::Location loc = cgf.getLoc(e->getExprLoc());
884 if (e->isStoredAsBoolean()) {
885 if (e->getType()->isBooleanType())
886 return builder.getBool(e->getBoolValue(), loc);
887 assert(e->getType()->isIntegerType() &&
888 "Expected int type for TypeTraitExpr");
889 return builder.getConstInt(loc, cgf.convertType(e->getType()),
890 (uint64_t)e->getBoolValue());
891 }
892 return builder.getConstInt(loc, e->getAPValue().getInt());
893 }
894 mlir::Value
895 VisitConceptSpecializationExpr(const ConceptSpecializationExpr *e) {
896 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
897 }
898 mlir::Value VisitRequiresExpr(const RequiresExpr *e) {
899 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
900 }
901 mlir::Value VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *e) {
902 mlir::Type type = cgf.convertType(e->getType());
903 mlir::Location loc = cgf.getLoc(e->getExprLoc());
904 return builder.getConstInt(loc, type, e->getValue());
905 }
906 mlir::Value VisitExpressionTraitExpr(const ExpressionTraitExpr *e) {
907 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
908 }
909 mlir::Value VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *e) {
910 cgf.cgm.errorNYI(e->getSourceRange(),
911 "ScalarExprEmitter: cxx pseudo destructor");
912 return {};
913 }
914 mlir::Value VisitCXXThrowExpr(const CXXThrowExpr *e) {
915 cgf.emitCXXThrowExpr(e);
916 return {};
917 }
918
919 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
920 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
921 }
922
923 /// Emit a conversion from the specified type to the specified destination
924 /// type, both of which are CIR scalar types.
925 /// TODO: do we need ScalarConversionOpts here? Should be done in another
926 /// pass.
927 mlir::Value
928 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
929 SourceLocation loc,
930 ScalarConversionOpts opts = ScalarConversionOpts()) {
931 // All conversions involving fixed point types should be handled by the
932 // emitFixedPoint family functions. This is done to prevent bloating up
933 // this function more, and although fixed point numbers are represented by
934 // integers, we do not want to follow any logic that assumes they should be
935 // treated as integers.
936 // TODO(leonardchan): When necessary, add another if statement checking for
937 // conversions to fixed point types from other types.
938 // conversions to fixed point types from other types.
939 if (srcType->isFixedPointType() || dstType->isFixedPointType()) {
940 cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions");
941 return {};
942 }
943
944 srcType = srcType.getCanonicalType();
945 dstType = dstType.getCanonicalType();
946 if (srcType == dstType) {
947 if (opts.emitImplicitIntegerSignChangeChecks)
948 cgf.getCIRGenModule().errorNYI(loc,
949 "implicit integer sign change checks");
950 return src;
951 }
952
953 if (dstType->isVoidType())
954 return {};
955
956 mlir::Type mlirSrcType = src.getType();
957
958 // Handle conversions to bool first, they are special: comparisons against
959 // 0.
960 if (dstType->isBooleanType())
961 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
962
963 mlir::Type mlirDstType = cgf.convertType(dstType);
964
965 if (srcType->isHalfType() &&
966 !cgf.getContext().getLangOpts().NativeHalfType) {
967 // Cast to FP using the intrinsic if the half type itself isn't supported.
968 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
969 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
970 cgf.getCIRGenModule().errorNYI(loc,
971 "cast via llvm.convert.from.fp16");
972 } else {
973 // Cast to other types through float, using either the intrinsic or
974 // FPExt, depending on whether the half type itself is supported (as
975 // opposed to operations on half, available with NativeHalfType).
976 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
977 cgf.getCIRGenModule().errorNYI(loc,
978 "cast via llvm.convert.from.fp16");
979 // FIXME(cir): For now lets pretend we shouldn't use the conversion
980 // intrinsics and insert a cast here unconditionally.
981 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
982 cgf.floatTy);
983 srcType = cgf.getContext().FloatTy;
984 mlirSrcType = cgf.floatTy;
985 }
986 }
987
988 // TODO(cir): LLVM codegen ignore conversions like int -> uint,
989 // is there anything to be done for CIR here?
990 if (mlirSrcType == mlirDstType) {
991 if (opts.emitImplicitIntegerSignChangeChecks)
992 cgf.getCIRGenModule().errorNYI(loc,
993 "implicit integer sign change checks");
994 return src;
995 }
996
997 // Handle pointer conversions next: pointers can only be converted to/from
998 // other pointers and integers. Check for pointer types in terms of LLVM, as
999 // some native types (like Obj-C id) may map to a pointer type.
1000 if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1001 cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
1002 return builder.getNullPtr(dstPT, src.getLoc());
1003 }
1004
1005 if (isa<cir::PointerType>(mlirSrcType)) {
1006 // Must be an ptr to int cast.
1007 assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");
1008 return builder.createPtrToInt(src, mlirDstType);
1009 }
1010
1011 // A scalar can be splatted to an extended vector of the same element type
1012 if (dstType->isExtVectorType() && !srcType->isVectorType()) {
1013 // Sema should add casts to make sure that the source expression's type
1014 // is the same as the vector's element type (sans qualifiers)
1015 assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1016 srcType.getTypePtr() &&
1017 "Splatted expr doesn't match with vector element type?");
1018
1019 cgf.getCIRGenModule().errorNYI(loc, "vector splatting");
1020 return {};
1021 }
1022
1023 if (srcType->isMatrixType() && dstType->isMatrixType()) {
1024 cgf.getCIRGenModule().errorNYI(loc,
1025 "matrix type to matrix type conversion");
1026 return {};
1027 }
1028 assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
1029 "Internal error: conversion between matrix type and scalar type");
1030
1031 // Finally, we have the arithmetic types or vectors of arithmetic types.
1032 mlir::Value res = nullptr;
1033 mlir::Type resTy = mlirDstType;
1034
1035 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1036
1037 if (mlirDstType != resTy) {
1038 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1039 cgf.getCIRGenModule().errorNYI(loc, "cast via llvm.convert.to.fp16");
1040 }
1041 // FIXME(cir): For now we never use FP16 conversion intrinsics even if
1042 // required by the target. Change that once this is implemented
1043 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1044 resTy);
1045 }
1046
1047 if (opts.emitImplicitIntegerTruncationChecks)
1048 cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");
1049
1050 if (opts.emitImplicitIntegerSignChangeChecks)
1051 cgf.getCIRGenModule().errorNYI(loc,
1052 "implicit integer sign change checks");
1053
1054 return res;
1055 }
1056
1057 BinOpInfo emitBinOps(const BinaryOperator *e,
1058 QualType promotionType = QualType()) {
1059 ignoreResultAssign = false;
1060 BinOpInfo result;
1061 result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
1062 result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
1063 if (!promotionType.isNull())
1064 result.fullType = promotionType;
1065 else
1066 result.fullType = e->getType();
1067 result.compType = result.fullType;
1068 if (const auto *vecType = result.fullType->getAs<VectorType>())
1069 result.compType = vecType->getElementType();
1070 result.opcode = e->getOpcode();
1071 result.loc = e->getSourceRange();
1072 // TODO(cir): Result.FPFeatures
1073 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1074 result.e = e;
1075 return result;
1076 }
1077
1078 mlir::Value emitMul(const BinOpInfo &ops);
1079 mlir::Value emitDiv(const BinOpInfo &ops);
1080 mlir::Value emitRem(const BinOpInfo &ops);
1081 mlir::Value emitAdd(const BinOpInfo &ops);
1082 mlir::Value emitSub(const BinOpInfo &ops);
1083 mlir::Value emitShl(const BinOpInfo &ops);
1084 mlir::Value emitShr(const BinOpInfo &ops);
1085 mlir::Value emitAnd(const BinOpInfo &ops);
1086 mlir::Value emitXor(const BinOpInfo &ops);
1087 mlir::Value emitOr(const BinOpInfo &ops);
1088
1089 LValue emitCompoundAssignLValue(
1090 const CompoundAssignOperator *e,
1091 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
1092 mlir::Value &result);
1093 mlir::Value
1094 emitCompoundAssign(const CompoundAssignOperator *e,
1095 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
1096
1097 // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
1098 // codegen.
1099 QualType getPromotionType(QualType ty) {
1100 const clang::ASTContext &ctx = cgf.getContext();
1101 if (auto *complexTy = ty->getAs<ComplexType>()) {
1102 QualType elementTy = complexTy->getElementType();
1103 if (elementTy.UseExcessPrecision(ctx))
1104 return ctx.getComplexType(ctx.FloatTy);
1105 }
1106
1107 if (ty.UseExcessPrecision(cgf.getContext())) {
1108 if (auto *vt = ty->getAs<VectorType>()) {
1109 unsigned numElements = vt->getNumElements();
1110 return ctx.getVectorType(ctx.FloatTy, numElements, vt->getVectorKind());
1111 }
1112 return cgf.getContext().FloatTy;
1113 }
1114
1115 return QualType();
1116 }
1117
1118// Binary operators and binary compound assignment operators.
1119#define HANDLEBINOP(OP) \
1120 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1121 QualType promotionTy = getPromotionType(e->getType()); \
1122 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1123 if (result && !promotionTy.isNull()) \
1124 result = emitUnPromotedValue(result, e->getType()); \
1125 return result; \
1126 } \
1127 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1128 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1129 }
1130
1131 HANDLEBINOP(Mul)
1132 HANDLEBINOP(Div)
1133 HANDLEBINOP(Rem)
1134 HANDLEBINOP(Add)
1135 HANDLEBINOP(Sub)
1136 HANDLEBINOP(Shl)
1137 HANDLEBINOP(Shr)
1139 HANDLEBINOP(Xor)
1141#undef HANDLEBINOP
1142
1143 mlir::Value emitCmp(const BinaryOperator *e) {
1144 ignoreResultAssign = false;
1145 const mlir::Location loc = cgf.getLoc(e->getExprLoc());
1146 mlir::Value result;
1147 QualType lhsTy = e->getLHS()->getType();
1148 QualType rhsTy = e->getRHS()->getType();
1149
1150 auto clangCmpToCIRCmp =
1151 [](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
1152 switch (clangCmp) {
1153 case BO_LT:
1154 return cir::CmpOpKind::lt;
1155 case BO_GT:
1156 return cir::CmpOpKind::gt;
1157 case BO_LE:
1158 return cir::CmpOpKind::le;
1159 case BO_GE:
1160 return cir::CmpOpKind::ge;
1161 case BO_EQ:
1162 return cir::CmpOpKind::eq;
1163 case BO_NE:
1164 return cir::CmpOpKind::ne;
1165 default:
1166 llvm_unreachable("unsupported comparison kind for cir.cmp");
1167 }
1168 };
1169
1170 cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
1171 if (lhsTy->getAs<MemberPointerType>()) {
1173 assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
1174 mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
1175 mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
1176 result = builder.createCompare(loc, kind, lhs, rhs);
1177 } else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
1178 BinOpInfo boInfo = emitBinOps(e);
1179 mlir::Value lhs = boInfo.lhs;
1180 mlir::Value rhs = boInfo.rhs;
1181
1182 if (lhsTy->isVectorType()) {
1183 if (!e->getType()->isVectorType()) {
1184 // If AltiVec, the comparison results in a numeric type, so we use
1185 // intrinsics comparing vectors and giving 0 or 1 as a result
1186 cgf.cgm.errorNYI(loc, "AltiVec comparison");
1187 } else {
1188 // Other kinds of vectors. Element-wise comparison returning
1189 // a vector.
1190 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1191 cgf.convertType(boInfo.fullType), kind,
1192 boInfo.lhs, boInfo.rhs);
1193 }
1194 } else if (boInfo.isFixedPointOp()) {
1196 cgf.cgm.errorNYI(loc, "fixed point comparisons");
1197 result = builder.getBool(false, loc);
1198 } else {
1199 // integers and pointers
1200 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1201 mlir::isa<cir::PointerType>(lhs.getType()) &&
1202 mlir::isa<cir::PointerType>(rhs.getType())) {
1203 cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");
1204 }
1205 result = builder.createCompare(loc, kind, lhs, rhs);
1206 }
1207 } else {
1208 assert((e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE) &&
1209 "Complex Comparison: can only be an equality comparison");
1210
1211 mlir::Value lhs;
1212 if (lhsTy->isAnyComplexType()) {
1213 lhs = cgf.emitComplexExpr(e->getLHS());
1214 } else {
1215 mlir::Value lhsReal = Visit(e->getLHS());
1216 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1217 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1218 }
1219
1220 mlir::Value rhs;
1221 if (rhsTy->isAnyComplexType()) {
1222 rhs = cgf.emitComplexExpr(e->getRHS());
1223 } else {
1224 mlir::Value rhsReal = Visit(e->getRHS());
1225 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1226 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1227 }
1228
1229 result = builder.createCompare(loc, kind, lhs, rhs);
1230 }
1231
1232 return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
1233 e->getExprLoc());
1234 }
1235
1236// Comparisons.
1237#define VISITCOMP(CODE) \
1238 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1239 VISITCOMP(LT)
1240 VISITCOMP(GT)
1241 VISITCOMP(LE)
1242 VISITCOMP(GE)
1243 VISITCOMP(EQ)
1244 VISITCOMP(NE)
1245#undef VISITCOMP
1246
1247 mlir::Value VisitBinAssign(const BinaryOperator *e) {
1248 const bool ignore = std::exchange(ignoreResultAssign, false);
1249
1250 mlir::Value rhs;
1251 LValue lhs;
1252
1253 switch (e->getLHS()->getType().getObjCLifetime()) {
1259 break;
1261 // __block variables need to have the rhs evaluated first, plus this
1262 // should improve codegen just a little.
1263 rhs = Visit(e->getRHS());
1265 // TODO(cir): This needs to be emitCheckedLValue() once we support
1266 // sanitizers
1267 lhs = cgf.emitLValue(e->getLHS());
1268
1269 // Store the value into the LHS. Bit-fields are handled specially because
1270 // the result is altered by the store, i.e., [C99 6.5.16p1]
1271 // 'An assignment expression has the value of the left operand after the
1272 // assignment...'.
1273 if (lhs.isBitField()) {
1275 cgf, cgf.getLoc(e->getSourceRange())};
1276 rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);
1277 } else {
1278 cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
1280 cgf, cgf.getLoc(e->getSourceRange())};
1281 cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);
1282 }
1283 }
1284
1285 // If the result is clearly ignored, return now.
1286 if (ignore)
1287 return nullptr;
1288
1289 // The result of an assignment in C is the assigned r-value.
1290 if (!cgf.getLangOpts().CPlusPlus)
1291 return rhs;
1292
1293 // If the lvalue is non-volatile, return the computed value of the
1294 // assignment.
1295 if (!lhs.isVolatile())
1296 return rhs;
1297
1298 // Otherwise, reload the value.
1299 return emitLoadOfLValue(lhs, e->getExprLoc());
1300 }
1301
1302 mlir::Value VisitBinComma(const BinaryOperator *e) {
1303 cgf.emitIgnoredExpr(e->getLHS());
1304 // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.
1305 return Visit(e->getRHS());
1306 }
1307
1308 mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {
1309 if (e->getType()->isVectorType()) {
1310 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1311 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1312 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1313
1314 mlir::Value lhs = Visit(e->getLHS());
1315 mlir::Value rhs = Visit(e->getRHS());
1316
1317 auto cmpOpKind = cir::CmpOpKind::ne;
1318 mlir::Type resTy = cgf.convertType(e->getType());
1319 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1320 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1321 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1322 return builder.createIntCast(vecOr, resTy);
1323 }
1324
1326 mlir::Type resTy = cgf.convertType(e->getType());
1327 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1328
1329 CIRGenFunction::ConditionalEvaluation eval(cgf);
1330
1331 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1332 auto resOp = cir::TernaryOp::create(
1333 builder, loc, lhsCondV, /*trueBuilder=*/
1334 [&](mlir::OpBuilder &b, mlir::Location loc) {
1335 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1336 b.getInsertionBlock()};
1337 cgf.curLexScope->setAsTernary();
1338 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1339 lexScope.forceCleanup({&res});
1340 cir::YieldOp::create(b, loc, res);
1341 },
1342 /*falseBuilder*/
1343 [&](mlir::OpBuilder &b, mlir::Location loc) {
1344 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1345 b.getInsertionBlock()};
1346 cgf.curLexScope->setAsTernary();
1347 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1348 cir::YieldOp::create(b, loc, res.getRes());
1349 });
1350 return maybePromoteBoolResult(resOp.getResult(), resTy);
1351 }
1352
1353 mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {
1354 if (e->getType()->isVectorType()) {
1355 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1356 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1357 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1358
1359 mlir::Value lhs = Visit(e->getLHS());
1360 mlir::Value rhs = Visit(e->getRHS());
1361
1362 auto cmpOpKind = cir::CmpOpKind::ne;
1363 mlir::Type resTy = cgf.convertType(e->getType());
1364 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1365 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1366 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1367 return builder.createIntCast(vecOr, resTy);
1368 }
1369
1371 mlir::Type resTy = cgf.convertType(e->getType());
1372 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1373
1374 CIRGenFunction::ConditionalEvaluation eval(cgf);
1375
1376 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1377 auto resOp = cir::TernaryOp::create(
1378 builder, loc, lhsCondV, /*trueBuilder=*/
1379 [&](mlir::OpBuilder &b, mlir::Location loc) {
1380 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1381 b.getInsertionBlock()};
1382 cgf.curLexScope->setAsTernary();
1383 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1384 cir::YieldOp::create(b, loc, res.getRes());
1385 },
1386 /*falseBuilder*/
1387 [&](mlir::OpBuilder &b, mlir::Location loc) {
1388 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1389 b.getInsertionBlock()};
1390 cgf.curLexScope->setAsTernary();
1391 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1392 lexScope.forceCleanup({&res});
1393 cir::YieldOp::create(b, loc, res);
1394 });
1395
1396 return maybePromoteBoolResult(resOp.getResult(), resTy);
1397 }
1398
1399 mlir::Value VisitBinPtrMemD(const BinaryOperator *e) {
1400 return emitLoadOfLValue(e);
1401 }
1402
1403 mlir::Value VisitBinPtrMemI(const BinaryOperator *e) {
1404 return emitLoadOfLValue(e);
1405 }
1406
1407 // Other Operators.
1408 mlir::Value VisitBlockExpr(const BlockExpr *e) {
1409 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: block");
1410 return {};
1411 }
1412
1413 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1414 return Visit(e->getChosenSubExpr());
1415 }
1416
1417 mlir::Value VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1418 cgf.cgm.errorNYI(e->getSourceRange(),
1419 "ScalarExprEmitter: objc string literal");
1420 return {};
1421 }
1422 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1423 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc boxed");
1424 return {};
1425 }
1426 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1427 cgf.cgm.errorNYI(e->getSourceRange(),
1428 "ScalarExprEmitter: objc array literal");
1429 return {};
1430 }
1431 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1432 cgf.cgm.errorNYI(e->getSourceRange(),
1433 "ScalarExprEmitter: objc dictionary literal");
1434 return {};
1435 }
1436
1437 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1438 mlir::Value src, unsigned numElementsDst) {
1439 static constexpr int64_t mask[] = {0, 1, 2, -1};
1440 return builder.createVecShuffle(
1441 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1442 }
1443
1444 // Create cast instructions for converting MLIR value \p Src to MLIR type \p
1445 // DstTy. \p Src has the same size as \p DstTy. Both are single value types
1446 // but could be scalar or vectors of different lengths, and either can be
1447 // pointer.
1448 //
1449 // There are 4 cases:
1450 // 1. non-pointer -> non-pointer : needs 1 bitcast
1451 // 2. pointer -> pointer : needs 1 bitcast or addrspacecast
1452 // 3. pointer -> non-pointer
1453 // a) pointer -> intptr_t : needs 1 ptrtoint
1454 // b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast
1455 // 4. non-pointer -> pointer
1456 // a) intptr_t -> pointer : needs 1 inttoptr
1457 // b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr
1458 //
1459 // Note: for cases 3b and 4b two casts are required since LLVM casts do not
1460 // allow casting directly between pointer types and non-integer non-pointer
1461 // types.
1462 mlir::Value createCastsForTypeOfSameSize(mlir::Value src, mlir::Type dstTy) {
1463 mlir::Type srcTy = src.getType();
1464
1465 // Case 1.
1466 if (!isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy))
1467 return builder.createBitcast(src, dstTy);
1468
1469 // Case 2.
1470 if (isa<cir::PointerType>(srcTy) && isa<cir::PointerType>(dstTy)) {
1471 cgf.cgm.errorNYI(
1472 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1473 return {};
1474 }
1475
1476 // Case 3.
1477 if (isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy)) {
1478 if (!isa<cir::IntType>(dstTy)) {
1479 cgf.cgm.errorNYI(
1480 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1481 }
1482
1483 cgf.cgm.errorNYI(
1484 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1485 return {};
1486 }
1487
1488 // Case 4b.
1489 if (!isa<cir::IntType>(srcTy)) {
1490 cgf.cgm.errorNYI(
1491 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1492 return {};
1493 }
1494 // Cases 4a and 4b.
1495 return builder.createIntToPtr(src, dstTy);
1496 }
1497
1498 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1499 mlir::Value src = cgf.emitScalarExpr(e->getSrcExpr());
1500 mlir::Type srcTy = src.getType();
1501 mlir::Type dstTy = cgf.convertType(e->getType());
1502
1503 unsigned numElementsSrc = isa<cir::VectorType>(srcTy)
1504 ? cast<cir::VectorType>(srcTy).getSize()
1505 : 0;
1506 unsigned numElementsDst = isa<cir::VectorType>(dstTy)
1507 ? cast<cir::VectorType>(dstTy).getSize()
1508 : 0;
1509
1510 // Use bit vector expansion for ext_vector_type boolean vectors.
1511 if (e->getType()->isExtVectorBoolType()) {
1512 cgf.cgm.errorNYI(e->getSourceRange(),
1513 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1514 return {};
1515 }
1516
1517 // Going from vec3 to non-vec3 is a special case and requires a shuffle
1518 // vector to get a vec4, then a bitcast if the target type is different.
1519 if (numElementsSrc == 3 && numElementsDst != 3) {
1520 cgf.cgm.errorNYI(e->getSourceRange(),
1521 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1522 "numElemsDst != 3");
1523 return {};
1524 }
1525
1526 // Going from non-vec3 to vec3 is a special case and requires a bitcast
1527 // to vec4 if the original type is not vec4, then a shuffle vector to
1528 // get a vec3.
1529 if (numElementsSrc != 3 && numElementsDst == 3) {
1530 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1531 auto dstElemTy = cast<cir::VectorType>(dstTy).getElementType();
1532 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1533 src = createCastsForTypeOfSameSize(src, dstVec4Ty);
1534 src = convertVec3AndVec4(builder, loc, src, 3);
1535 return src;
1536 }
1537
1538 return createCastsForTypeOfSameSize(src, dstTy);
1539 }
1540
1541 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1542 return cgf.emitAtomicExpr(e).getValue();
1543 }
1544};
1545
1546LValue ScalarExprEmitter::emitCompoundAssignLValue(
1547 const CompoundAssignOperator *e,
1548 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
1549 mlir::Value &result) {
1551 return cgf.emitScalarCompoundAssignWithComplex(e, result);
1552
1553 QualType lhsTy = e->getLHS()->getType();
1554 BinOpInfo opInfo;
1555
1556 // Emit the RHS first. __block variables need to have the rhs evaluated
1557 // first, plus this should improve codegen a little.
1558
1559 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
1560 if (promotionTypeCR.isNull())
1561 promotionTypeCR = e->getComputationResultType();
1562
1563 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
1564 QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
1565
1566 if (!promotionTypeRHS.isNull())
1567 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
1568 else
1569 opInfo.rhs = Visit(e->getRHS());
1570
1571 opInfo.fullType = promotionTypeCR;
1572 opInfo.compType = opInfo.fullType;
1573 if (const auto *vecType = opInfo.fullType->getAs<VectorType>())
1574 opInfo.compType = vecType->getElementType();
1575 opInfo.opcode = e->getOpcode();
1576 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1577 opInfo.e = e;
1578 opInfo.loc = e->getSourceRange();
1579
1580 // Load/convert the LHS
1581 LValue lhsLV = cgf.emitLValue(e->getLHS());
1582
1583 if (lhsTy->getAs<AtomicType>()) {
1584 cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
1585 return LValue();
1586 }
1587
1588 opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
1589
1590 CIRGenFunction::SourceLocRAIIObject sourceloc{
1591 cgf, cgf.getLoc(e->getSourceRange())};
1592 SourceLocation loc = e->getExprLoc();
1593 if (!promotionTypeLHS.isNull())
1594 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1595 else
1596 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1597 e->getComputationLHSType(), loc);
1598
1599 // Expand the binary operator.
1600 result = (this->*func)(opInfo);
1601
1602 // Convert the result back to the LHS type,
1603 // potentially with Implicit Conversion sanitizer check.
1604 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1605 ScalarConversionOpts(cgf.sanOpts));
1606
1607 // Store the result value into the LHS lvalue. Bit-fields are handled
1608 // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
1609 // 'An assignment expression has the value of the left operand after the
1610 // assignment...'.
1611 if (lhsLV.isBitField())
1612 cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);
1613 else
1614 cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
1615
1616 if (cgf.getLangOpts().OpenMP)
1617 cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
1618
1619 return lhsLV;
1620}
1621
1622mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1623 mlir::Value value,
1624 CastKind kind,
1625 QualType destTy) {
1626 cir::CastKind castOpKind;
1627 switch (kind) {
1628 case CK_FloatingComplexToReal:
1629 castOpKind = cir::CastKind::float_complex_to_real;
1630 break;
1631 case CK_IntegralComplexToReal:
1632 castOpKind = cir::CastKind::int_complex_to_real;
1633 break;
1634 case CK_FloatingComplexToBoolean:
1635 castOpKind = cir::CastKind::float_complex_to_bool;
1636 break;
1637 case CK_IntegralComplexToBoolean:
1638 castOpKind = cir::CastKind::int_complex_to_bool;
1639 break;
1640 default:
1641 llvm_unreachable("invalid complex-to-scalar cast kind");
1642 }
1643
1644 return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));
1645}
1646
1647mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
1648 QualType promotionType) {
1649 e = e->IgnoreParens();
1650 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
1651 switch (bo->getOpcode()) {
1652#define HANDLE_BINOP(OP) \
1653 case BO_##OP: \
1654 return emit##OP(emitBinOps(bo, promotionType));
1655 HANDLE_BINOP(Add)
1656 HANDLE_BINOP(Sub)
1657 HANDLE_BINOP(Mul)
1658 HANDLE_BINOP(Div)
1659#undef HANDLE_BINOP
1660 default:
1661 break;
1662 }
1663 } else if (const auto *uo = dyn_cast<UnaryOperator>(e)) {
1664 switch (uo->getOpcode()) {
1665 case UO_Imag:
1666 case UO_Real:
1667 return VisitRealImag(uo, promotionType);
1668 case UO_Minus:
1669 return VisitUnaryMinus(uo, promotionType);
1670 case UO_Plus:
1671 return VisitUnaryPlus(uo, promotionType);
1672 default:
1673 break;
1674 }
1675 }
1676 mlir::Value result = Visit(const_cast<Expr *>(e));
1677 if (result) {
1678 if (!promotionType.isNull())
1679 return emitPromotedValue(result, promotionType);
1680 return emitUnPromotedValue(result, e->getType());
1681 }
1682 return result;
1683}
1684
1685mlir::Value ScalarExprEmitter::emitCompoundAssign(
1686 const CompoundAssignOperator *e,
1687 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
1688
1689 bool ignore = std::exchange(ignoreResultAssign, false);
1690 mlir::Value rhs;
1691 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1692
1693 // If the result is clearly ignored, return now.
1694 if (ignore)
1695 return {};
1696
1697 // The result of an assignment in C is the assigned r-value.
1698 if (!cgf.getLangOpts().CPlusPlus)
1699 return rhs;
1700
1701 // If the lvalue is non-volatile, return the computed value of the assignment.
1702 if (!lhs.isVolatile())
1703 return rhs;
1704
1705 // Otherwise, reload the value.
1706 return emitLoadOfLValue(lhs, e->getExprLoc());
1707}
1708
1709mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1710 CIRGenFunction::FullExprCleanupScope scope(cgf, e->getSubExpr());
1711 mlir::Value v = Visit(e->getSubExpr());
1712 // Defend against dominance problems caused by jumps out of expression
1713 // evaluation through the shared cleanup block.
1714 scope.exit({&v});
1715 return v;
1716}
1717
1718} // namespace
1719
1720LValue
1722 ScalarExprEmitter emitter(*this, builder);
1723 mlir::Value result;
1724 switch (e->getOpcode()) {
1725#define COMPOUND_OP(Op) \
1726 case BO_##Op##Assign: \
1727 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1728 result)
1729 COMPOUND_OP(Mul);
1730 COMPOUND_OP(Div);
1731 COMPOUND_OP(Rem);
1732 COMPOUND_OP(Add);
1733 COMPOUND_OP(Sub);
1734 COMPOUND_OP(Shl);
1735 COMPOUND_OP(Shr);
1737 COMPOUND_OP(Xor);
1738 COMPOUND_OP(Or);
1739#undef COMPOUND_OP
1740
1741 case BO_PtrMemD:
1742 case BO_PtrMemI:
1743 case BO_Mul:
1744 case BO_Div:
1745 case BO_Rem:
1746 case BO_Add:
1747 case BO_Sub:
1748 case BO_Shl:
1749 case BO_Shr:
1750 case BO_LT:
1751 case BO_GT:
1752 case BO_LE:
1753 case BO_GE:
1754 case BO_EQ:
1755 case BO_NE:
1756 case BO_Cmp:
1757 case BO_And:
1758 case BO_Xor:
1759 case BO_Or:
1760 case BO_LAnd:
1761 case BO_LOr:
1762 case BO_Assign:
1763 case BO_Comma:
1764 llvm_unreachable("Not valid compound assignment operators");
1765 }
1766 llvm_unreachable("Unhandled compound assignment operator");
1767}
1768
1769/// Emit the computation of the specified expression of scalar type.
1771 bool ignoreResultAssign) {
1772 assert(e && hasScalarEvaluationKind(e->getType()) &&
1773 "Invalid scalar expression to emit");
1774
1775 return ScalarExprEmitter(*this, builder, ignoreResultAssign)
1776 .Visit(const_cast<Expr *>(e));
1777}
1778
1780 QualType promotionType) {
1781 if (!promotionType.isNull())
1782 return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);
1783 return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1784}
1785
1786[[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {
1787 // If a null pointer expression's type is the C++0x nullptr_t and
1788 // the expression is not a simple literal, it must be evaluated
1789 // for its potential side effects.
1791 return false;
1792 return e->getType()->isNullPtrType();
1793}
1794
1795/// If \p e is a widened promoted integer, get its base (unpromoted) type.
1796static std::optional<QualType>
1797getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {
1798 const Expr *base = e->IgnoreImpCasts();
1799 if (e == base)
1800 return std::nullopt;
1801
1802 QualType baseTy = base->getType();
1803 if (!astContext.isPromotableIntegerType(baseTy) ||
1804 astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))
1805 return std::nullopt;
1806
1807 return baseTy;
1808}
1809
1810/// Check if \p e is a widened promoted integer.
1811[[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,
1812 const Expr *e) {
1813 return getUnwidenedIntegerType(astContext, e).has_value();
1814}
1815
1816/// Check if we can skip the overflow check for \p Op.
1817[[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,
1818 const BinOpInfo &op) {
1819 assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1820 "Expected a unary or binary operator");
1821
1822 // If the binop has constant inputs and we can prove there is no overflow,
1823 // we can elide the overflow check.
1824 if (!op.mayHaveIntegerOverflow())
1825 return true;
1826
1827 // If a unary op has a widened operand, the op cannot overflow.
1828 if (const auto *uo = dyn_cast<UnaryOperator>(op.e))
1829 return !uo->canOverflow();
1830
1831 // We usually don't need overflow checks for binops with widened operands.
1832 // Multiplication with promoted unsigned operands is a special case.
1833 const auto *bo = cast<BinaryOperator>(op.e);
1834 std::optional<QualType> optionalLHSTy =
1835 getUnwidenedIntegerType(astContext, bo->getLHS());
1836 if (!optionalLHSTy)
1837 return false;
1838
1839 std::optional<QualType> optionalRHSTy =
1840 getUnwidenedIntegerType(astContext, bo->getRHS());
1841 if (!optionalRHSTy)
1842 return false;
1843
1844 QualType lhsTy = *optionalLHSTy;
1845 QualType rhsTy = *optionalRHSTy;
1846
1847 // This is the simple case: binops without unsigned multiplication, and with
1848 // widened operands. No overflow check is needed here.
1849 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1850 !lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())
1851 return true;
1852
1853 // For unsigned multiplication the overflow check can be elided if either one
1854 // of the unpromoted types are less than half the size of the promoted type.
1855 unsigned promotedSize = astContext.getTypeSize(op.e->getType());
1856 return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||
1857 (2 * astContext.getTypeSize(rhsTy)) < promotedSize;
1858}
1859
1860/// Emit pointer + index arithmetic.
1862 const BinOpInfo &op,
1863 bool isSubtraction) {
1864 // Must have binary (not unary) expr here. Unary pointer
1865 // increment/decrement doesn't use this path.
1867
1868 mlir::Value pointer = op.lhs;
1869 Expr *pointerOperand = expr->getLHS();
1870 mlir::Value index = op.rhs;
1871 Expr *indexOperand = expr->getRHS();
1872
1873 // In the case of subtraction, the FE has ensured that the LHS is always the
1874 // pointer. However, addition can have the pointer on either side. We will
1875 // always have a pointer operand and an integer operand, so if the LHS wasn't
1876 // a pointer, we need to swap our values.
1877 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1878 std::swap(pointer, index);
1879 std::swap(pointerOperand, indexOperand);
1880 }
1881 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1882 "Need a pointer operand");
1883 assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");
1884
1885 // Some versions of glibc and gcc use idioms (particularly in their malloc
1886 // routines) that add a pointer-sized integer (known to be a pointer value)
1887 // to a null pointer in order to cast the value back to an integer or as
1888 // part of a pointer alignment algorithm. This is undefined behavior, but
1889 // we'd like to be able to compile programs that use it.
1890 //
1891 // Normally, we'd generate a GEP with a null-pointer base here in response
1892 // to that code, but it's also UB to dereference a pointer created that
1893 // way. Instead (as an acknowledged hack to tolerate the idiom) we will
1894 // generate a direct cast of the integer value to a pointer.
1895 //
1896 // The idiom (p = nullptr + N) is not met if any of the following are true:
1897 //
1898 // The operation is subtraction.
1899 // The index is not pointer-sized.
1900 // The pointer type is not byte-sized.
1901 //
1903 cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))
1904 return cgf.getBuilder().createIntToPtr(index, pointer.getType());
1905
1906 // Differently from LLVM codegen, ABI bits for index sizes is handled during
1907 // LLVM lowering.
1908
1909 // If this is subtraction, negate the index.
1910 if (isSubtraction)
1911 index = cgf.getBuilder().createNeg(cgf.getLoc(op.e->getExprLoc()), index);
1912
1914
1915 const PointerType *pointerType =
1916 pointerOperand->getType()->getAs<PointerType>();
1917 if (!pointerType) {
1918 cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");
1919 return nullptr;
1920 }
1921
1922 QualType elementType = pointerType->getPointeeType();
1923 if (const VariableArrayType *vla =
1924 cgf.getContext().getAsVariableArrayType(elementType)) {
1925 mlir::Value numElements = cgf.getVLASize(vla).numElts;
1926 mlir::Location loc = cgf.getLoc(op.e->getExprLoc());
1927 index = cgf.getBuilder().createCast(cir::CastKind::integral, index,
1928 numElements.getType());
1929 // GEP indexes are signed, and scaling an index isn't permitted to
1930 // signed-overflow, so we use the same semantics for our explicit
1931 // multiply. We suppress this if overflow is not undefined behavior.
1932 cir::OverflowBehavior overflowBehavior =
1933 cgf.getLangOpts().PointerOverflowDefined
1936 index =
1937 cgf.getBuilder().createMul(loc, index, numElements, overflowBehavior);
1939 return cir::PtrStrideOp::create(cgf.getBuilder(), loc, pointer.getType(),
1940 pointer, index);
1941 }
1942
1944 return cir::PtrStrideOp::create(cgf.getBuilder(),
1945 cgf.getLoc(op.e->getExprLoc()),
1946 pointer.getType(), pointer, index);
1947}
1948
1949static bool isIntegerVectorBinOp(mlir::Type ty) {
1950 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1951 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1952}
1953
1954mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {
1955 const mlir::Location loc = cgf.getLoc(ops.loc);
1956 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
1957 ops.compType->isSignedIntegerOrEnumerationType()) {
1958 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1959 case LangOptions::SOB_Defined:
1960 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1961 return builder.createMul(loc, ops.lhs, ops.rhs);
1962 [[fallthrough]];
1963 case LangOptions::SOB_Undefined:
1964 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1965 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1966 [[fallthrough]];
1967 case LangOptions::SOB_Trapping:
1968 if (canElideOverflowCheck(cgf.getContext(), ops))
1969 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1970 cgf.cgm.errorNYI("sanitizers");
1971 }
1972 }
1973 if (ops.fullType->isConstantMatrixType()) {
1975 cgf.cgm.errorNYI("matrix types");
1976 return nullptr;
1977 }
1978 if (ops.compType->isUnsignedIntegerType() &&
1979 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1980 !canElideOverflowCheck(cgf.getContext(), ops))
1981 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1982
1983 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1984 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1985 return builder.createFMul(loc, ops.lhs, ops.rhs);
1986 }
1987
1988 if (ops.isFixedPointOp()) {
1990 cgf.cgm.errorNYI("fixed point");
1991 return nullptr;
1992 }
1993
1994 return cir::MulOp::create(builder, cgf.getLoc(ops.loc),
1995 cgf.convertType(ops.fullType), ops.lhs, ops.rhs);
1996}
1997mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
1998 const mlir::Location loc = cgf.getLoc(ops.loc);
1999 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2000 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2001 return builder.createFDiv(loc, ops.lhs, ops.rhs);
2002 }
2003 return cir::DivOp::create(builder, loc, cgf.convertType(ops.fullType),
2004 ops.lhs, ops.rhs);
2005}
2006mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
2007 const mlir::Location loc = cgf.getLoc(ops.loc);
2008 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2009 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2010 return builder.createFRem(loc, ops.lhs, ops.rhs);
2011 }
2012 return cir::RemOp::create(builder, loc, cgf.convertType(ops.fullType),
2013 ops.lhs, ops.rhs);
2014}
2015
2016mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
2017 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2018 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2019 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/
2020 false);
2021
2022 const mlir::Location loc = cgf.getLoc(ops.loc);
2023 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2024 ops.compType->isSignedIntegerOrEnumerationType()) {
2025 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2026 case LangOptions::SOB_Defined:
2027 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2028 return builder.createAdd(loc, ops.lhs, ops.rhs);
2029 [[fallthrough]];
2030 case LangOptions::SOB_Undefined:
2031 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2032 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2033 [[fallthrough]];
2034 case LangOptions::SOB_Trapping:
2035 if (canElideOverflowCheck(cgf.getContext(), ops))
2036 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2037 cgf.cgm.errorNYI("sanitizers");
2038 }
2039 }
2040 if (ops.fullType->isConstantMatrixType()) {
2042 cgf.cgm.errorNYI("matrix types");
2043 return nullptr;
2044 }
2045
2046 if (ops.compType->isUnsignedIntegerType() &&
2047 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2048 !canElideOverflowCheck(cgf.getContext(), ops))
2049 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2050
2051 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2052 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2053 return builder.createFAdd(loc, ops.lhs, ops.rhs);
2054 }
2055
2056 if (ops.isFixedPointOp()) {
2058 cgf.cgm.errorNYI("fixed point");
2059 return {};
2060 }
2061
2062 return builder.createAdd(loc, ops.lhs, ops.rhs);
2063}
2064
2065mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
2066 const mlir::Location loc = cgf.getLoc(ops.loc);
2067 // The LHS is always a pointer if either side is.
2068 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2069 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2070 ops.compType->isSignedIntegerOrEnumerationType()) {
2071 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2072 case LangOptions::SOB_Defined: {
2073 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2074 return builder.createSub(loc, ops.lhs, ops.rhs);
2075 [[fallthrough]];
2076 }
2077 case LangOptions::SOB_Undefined:
2078 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2079 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2080 [[fallthrough]];
2081 case LangOptions::SOB_Trapping:
2082 if (canElideOverflowCheck(cgf.getContext(), ops))
2083 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2084 cgf.cgm.errorNYI("sanitizers");
2085 }
2086 }
2087
2088 if (ops.fullType->isConstantMatrixType()) {
2090 cgf.cgm.errorNYI("matrix types");
2091 return nullptr;
2092 }
2093
2094 if (ops.compType->isUnsignedIntegerType() &&
2095 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2096 !canElideOverflowCheck(cgf.getContext(), ops))
2097 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2098
2099 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2100 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2101 return builder.createFSub(loc, ops.lhs, ops.rhs);
2102 }
2103
2104 if (ops.isFixedPointOp()) {
2106 cgf.cgm.errorNYI("fixed point");
2107 return {};
2108 }
2109
2110 return builder.createSub(loc, ops.lhs, ops.rhs);
2111 }
2112
2113 // If the RHS is not a pointer, then we have normal pointer
2114 // arithmetic.
2115 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2116 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);
2117
2118 // Otherwise, this is a pointer subtraction
2119
2120 // Do the raw subtraction part.
2121 //
2122 // TODO(cir): note for LLVM lowering out of this; when expanding this into
2123 // LLVM we shall take VLA's, division by element size, etc.
2124 //
2125 // See more in `EmitSub` in CGExprScalar.cpp.
2127 return cir::PtrDiffOp::create(builder, cgf.getLoc(ops.loc), cgf.ptrDiffTy,
2128 ops.lhs, ops.rhs);
2129}
2130
2131mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
2132 // TODO: This misses out on the sanitizer check below.
2133 if (ops.isFixedPointOp()) {
2135 cgf.cgm.errorNYI("fixed point");
2136 return {};
2137 }
2138
2139 // CIR accepts shift between different types, meaning nothing special
2140 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2141 // promote or truncate the RHS to the same size as the LHS.
2142
2143 bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&
2144 ops.compType->hasSignedIntegerRepresentation() &&
2146 !cgf.getLangOpts().CPlusPlus20;
2147 bool sanitizeUnsignedBase =
2148 cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&
2149 ops.compType->hasUnsignedIntegerRepresentation();
2150 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2151 bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);
2152
2153 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2154 if (cgf.getLangOpts().OpenCL)
2155 cgf.cgm.errorNYI("opencl");
2156 else if ((sanitizeBase || sanitizeExponent) &&
2157 mlir::isa<cir::IntType>(ops.lhs.getType()))
2158 cgf.cgm.errorNYI("sanitizers");
2159
2160 return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2161}
2162
2163mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
2164 // TODO: This misses out on the sanitizer check below.
2165 if (ops.isFixedPointOp()) {
2167 cgf.cgm.errorNYI("fixed point");
2168 return {};
2169 }
2170
2171 // CIR accepts shift between different types, meaning nothing special
2172 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2173 // promote or truncate the RHS to the same size as the LHS.
2174
2175 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2176 if (cgf.getLangOpts().OpenCL)
2177 cgf.cgm.errorNYI("opencl");
2178 else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&
2179 mlir::isa<cir::IntType>(ops.lhs.getType()))
2180 cgf.cgm.errorNYI("sanitizers");
2181
2182 // Note that we don't need to distinguish unsigned treatment at this
2183 // point since it will be handled later by LLVM lowering.
2184 return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2185}
2186
2187mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {
2188 return cir::AndOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2189}
2190mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {
2191 return cir::XorOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2192}
2193mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {
2194 return cir::OrOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2195}
2196
2197// Emit code for an explicit or implicit cast. Implicit
2198// casts have to handle a more broad range of conversions than explicit
2199// casts, as they handle things like function to ptr-to-function decay
2200// etc.
2201mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
2202 Expr *subExpr = ce->getSubExpr();
2203 QualType destTy = ce->getType();
2204 CastKind kind = ce->getCastKind();
2205
2206 // These cases are generally not written to ignore the result of evaluating
2207 // their sub-expressions, so we clear this now.
2208 ignoreResultAssign = false;
2209
2210 switch (kind) {
2211 case clang::CK_Dependent:
2212 llvm_unreachable("dependent cast kind in CIR gen!");
2213 case clang::CK_BuiltinFnToFnPtr:
2214 llvm_unreachable("builtin functions are handled elsewhere");
2215 case CK_LValueBitCast:
2216 case CK_LValueToRValueBitCast: {
2217 LValue sourceLVal = cgf.emitLValue(subExpr);
2218 Address sourceAddr = sourceLVal.getAddress();
2219
2220 mlir::Type destElemTy = cgf.convertTypeForMem(destTy);
2221 Address destAddr = sourceAddr.withElementType(cgf.getBuilder(), destElemTy);
2222 LValue destLVal = cgf.makeAddrLValue(destAddr, destTy);
2224 return emitLoadOfLValue(destLVal, ce->getExprLoc());
2225 }
2226
2227 case CK_CPointerToObjCPointerCast:
2228 case CK_BlockPointerToObjCPointerCast:
2229 case CK_AnyPointerToBlockPointerCast:
2230 case CK_BitCast: {
2231 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2232 mlir::Type dstTy = cgf.convertType(destTy);
2233
2235
2236 if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
2237 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2238 "sanitizer support");
2239
2240 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2241 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2242 "strict vtable pointers");
2243
2244 // Update heapallocsite metadata when there is an explicit pointer cast.
2246
2247 // If Src is a fixed vector and Dst is a scalable vector, and both have the
2248 // same element type, use the llvm.vector.insert intrinsic to perform the
2249 // bitcast.
2251
2252 // If Src is a scalable vector and Dst is a fixed vector, and both have the
2253 // same element type, use the llvm.vector.extract intrinsic to perform the
2254 // bitcast.
2256
2257 // Perform VLAT <-> VLST bitcast through memory.
2258 // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
2259 // require the element types of the vectors to be the same, we
2260 // need to keep this around for bitcasts between VLAT <-> VLST where
2261 // the element types of the vectors are not the same, until we figure
2262 // out a better way of doing these casts.
2264
2265 return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
2266 src, dstTy);
2267 }
2268 case CK_AddressSpaceConversion: {
2269 Expr::EvalResult result;
2270 if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
2271 result.Val.isNullPointer()) {
2272 // If e has side effect, it is emitted even if its final result is a
2273 // null pointer. In that case, a DCE pass should be able to
2274 // eliminate the useless instructions emitted during translating E.
2275 if (result.HasSideEffects)
2276 Visit(subExpr);
2277 return cgf.cgm.emitNullConstant(destTy,
2278 cgf.getLoc(subExpr->getExprLoc()));
2279 }
2280 return cgf.performAddrSpaceCast(Visit(subExpr), convertType(destTy));
2281 }
2282
2283 case CK_AtomicToNonAtomic:
2284 case CK_NonAtomicToAtomic:
2285 case CK_UserDefinedConversion:
2286 return Visit(const_cast<Expr *>(subExpr));
2287 case CK_NoOp:
2288 return ce->changesVolatileQualification() ? emitLoadOfLValue(ce)
2289 : Visit(subExpr);
2290 case CK_IntegralToPointer: {
2291 mlir::Type destCIRTy = cgf.convertType(destTy);
2292 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2293
2294 // Properly resize by casting to an int of the same size as the pointer.
2295 // Clang's IntegralToPointer includes 'bool' as the source, but in CIR
2296 // 'bool' is not an integral type. So check the source type to get the
2297 // correct CIR conversion.
2298 mlir::Type middleTy = cgf.cgm.getDataLayout().getIntPtrType(destCIRTy);
2299 mlir::Value middleVal = builder.createCast(
2300 subExpr->getType()->isBooleanType() ? cir::CastKind::bool_to_int
2301 : cir::CastKind::integral,
2302 src, middleTy);
2303
2304 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) {
2305 cgf.cgm.errorNYI(subExpr->getSourceRange(),
2306 "IntegralToPointer: strict vtable pointers");
2307 return {};
2308 }
2309
2310 return builder.createIntToPtr(middleVal, destCIRTy);
2311 }
2312
2313 case CK_BaseToDerived: {
2314 const CXXRecordDecl *derivedClassDecl = destTy->getPointeeCXXRecordDecl();
2315 assert(derivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
2316 Address base = cgf.emitPointerWithAlignment(subExpr);
2317 Address derived = cgf.getAddressOfDerivedClass(
2318 cgf.getLoc(ce->getSourceRange()), base, derivedClassDecl, ce->path(),
2320
2321 // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
2322 // performed and the object is not of the derived type.
2324
2325 return cgf.getAsNaturalPointerTo(derived, ce->getType()->getPointeeType());
2326 }
2327 case CK_UncheckedDerivedToBase:
2328 case CK_DerivedToBase: {
2329 // The EmitPointerWithAlignment path does this fine; just discard
2330 // the alignment.
2332 ce->getType()->getPointeeType());
2333 }
2334 case CK_Dynamic: {
2335 Address v = cgf.emitPointerWithAlignment(subExpr);
2336 const auto *dce = cast<CXXDynamicCastExpr>(ce);
2337 return cgf.emitDynamicCast(v, dce);
2338 }
2339 case CK_ArrayToPointerDecay:
2340 return cgf.emitArrayToPointerDecay(subExpr).getPointer();
2341
2342 case CK_NullToPointer: {
2343 if (mustVisitNullValue(subExpr))
2344 cgf.emitIgnoredExpr(subExpr);
2345
2346 // Note that DestTy is used as the MLIR type instead of a custom
2347 // nullptr type.
2348 mlir::Type ty = cgf.convertType(destTy);
2349 return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
2350 }
2351
2352 case CK_NullToMemberPointer: {
2353 if (mustVisitNullValue(subExpr))
2354 cgf.emitIgnoredExpr(subExpr);
2355
2357
2358 const MemberPointerType *mpt = ce->getType()->getAs<MemberPointerType>();
2359 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2360 return cgf.getBuilder().getConstant(
2361 loc, cgf.cgm.emitNullMemberAttr(destTy, mpt));
2362 }
2363
2364 case CK_ReinterpretMemberPointer: {
2365 mlir::Value src = Visit(subExpr);
2366 return builder.createBitcast(cgf.getLoc(subExpr->getExprLoc()), src,
2367 cgf.convertType(destTy));
2368 }
2369 case CK_BaseToDerivedMemberPointer:
2370 case CK_DerivedToBaseMemberPointer: {
2371 mlir::Value src = Visit(subExpr);
2372
2374
2375 QualType derivedTy =
2376 kind == CK_DerivedToBaseMemberPointer ? subExpr->getType() : destTy;
2377 const auto *mpType = derivedTy->castAs<MemberPointerType>();
2378 NestedNameSpecifier qualifier = mpType->getQualifier();
2379 assert(qualifier && "member pointer without class qualifier");
2380 const Type *qualifierType = qualifier.getAsType();
2381 assert(qualifierType && "member pointer qualifier is not a type");
2382 const CXXRecordDecl *derivedClass = qualifierType->getAsCXXRecordDecl();
2383 CharUnits offset =
2384 cgf.cgm.computeNonVirtualBaseClassOffset(derivedClass, ce->path());
2385
2386 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2387 mlir::Type resultTy = cgf.convertType(destTy);
2388 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.getQuantity());
2389
2390 if (subExpr->getType()->isMemberFunctionPointerType()) {
2391 if (kind == CK_BaseToDerivedMemberPointer)
2392 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2393 offsetAttr);
2394 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2395 }
2396
2397 if (kind == CK_BaseToDerivedMemberPointer)
2398 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2399 offsetAttr);
2400 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2401 offsetAttr);
2402 }
2403
2404 case CK_LValueToRValue:
2405 assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
2406 assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
2407 return Visit(const_cast<Expr *>(subExpr));
2408
2409 case CK_IntegralCast: {
2410 ScalarConversionOpts opts;
2411 if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2412 if (!ice->isPartOfExplicitCast())
2413 opts = ScalarConversionOpts(cgf.sanOpts);
2414 }
2415 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2416 ce->getExprLoc(), opts);
2417 }
2418
2419 case CK_FloatingComplexToReal:
2420 case CK_IntegralComplexToReal:
2421 case CK_FloatingComplexToBoolean:
2422 case CK_IntegralComplexToBoolean: {
2423 mlir::Value value = cgf.emitComplexExpr(subExpr);
2424 return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,
2425 kind, destTy);
2426 }
2427
2428 case CK_FloatingRealToComplex:
2429 case CK_FloatingComplexCast:
2430 case CK_IntegralRealToComplex:
2431 case CK_IntegralComplexCast:
2432 case CK_IntegralComplexToFloatingComplex:
2433 case CK_FloatingComplexToIntegralComplex:
2434 llvm_unreachable("scalar cast to non-scalar value");
2435
2436 case CK_PointerToIntegral: {
2437 assert(!destTy->isBooleanType() && "bool should use PointerToBool");
2438 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2439 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2440 "strict vtable pointers");
2441 return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));
2442 }
2443 case CK_ToVoid:
2444 cgf.emitIgnoredExpr(subExpr);
2445 return {};
2446
2447 case CK_IntegralToFloating:
2448 case CK_FloatingToIntegral:
2449 case CK_FloatingCast:
2450 case CK_FixedPointToFloating:
2451 case CK_FloatingToFixedPoint: {
2452 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
2453 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2454 "fixed point casts");
2455 return {};
2456 }
2457 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2458 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2459 ce->getExprLoc());
2460 }
2461
2462 case CK_IntegralToBoolean:
2463 return emitIntToBoolConversion(Visit(subExpr),
2464 cgf.getLoc(ce->getSourceRange()));
2465
2466 case CK_PointerToBoolean:
2467 return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());
2468 case CK_FloatingToBoolean:
2469 return emitFloatToBoolConversion(Visit(subExpr),
2470 cgf.getLoc(subExpr->getExprLoc()));
2471 case CK_MemberPointerToBoolean: {
2472 mlir::Value memPtr = Visit(subExpr);
2473 return builder.createCast(cgf.getLoc(ce->getSourceRange()),
2474 cir::CastKind::member_ptr_to_bool, memPtr,
2475 cgf.convertType(destTy));
2476 }
2477
2478 case CK_VectorSplat: {
2479 // Create a vector object and fill all elements with the same scalar value.
2480 assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
2481 return cir::VecSplatOp::create(builder,
2482 cgf.getLoc(subExpr->getSourceRange()),
2483 cgf.convertType(destTy), Visit(subExpr));
2484 }
2485 case CK_FunctionToPointerDecay:
2486 return cgf.emitLValue(subExpr).getPointer();
2487
2488 default:
2489 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2490 "CastExpr: ", ce->getCastKindName());
2491 }
2492 return {};
2493}
2494
2495mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
2497 return emitLoadOfLValue(e);
2498
2499 auto v = cgf.emitCallExpr(e).getValue();
2501 return v;
2502}
2503
2504mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2505 // TODO(cir): The classic codegen calls tryEmitAsConstant() here. Folding
2506 // constants sound like work for MLIR optimizers, but we'll keep an assertion
2507 // for now.
2509 Expr::EvalResult result;
2510 if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {
2511 llvm::APSInt value = result.Val.getInt();
2512 cgf.emitIgnoredExpr(e->getBase());
2513 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2514 // The constant is folded from an APSInt with the source-type's bit width
2515 // (1 for bool), but the AST's expression type is what later consumers of
2516 // this value see. For a bool member we have to emit a !cir.bool constant
2517 // -- otherwise downstream ops (cir.call into a bool parameter, cir.if /
2518 // cir.ternary on the value, ...) would all reject the !cir.int<u, 1> the
2519 // raw APSInt would produce.
2520 if (e->getType()->isBooleanType())
2521 return builder.getBool(value.getBoolValue(), loc);
2522 return builder.getConstInt(loc, value);
2523 }
2524 return emitLoadOfLValue(e);
2525}
2526
2527mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2528 const unsigned numInitElements = e->getNumInits();
2529
2530 [[maybe_unused]] const bool ignore = std::exchange(ignoreResultAssign, false);
2531 assert((ignore == false ||
2532 (numInitElements == 0 && e->getType()->isVoidType())) &&
2533 "init list ignored");
2534
2535 if (e->hadArrayRangeDesignator()) {
2536 cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
2537 return {};
2538 }
2539
2540 if (e->getType()->isVectorType()) {
2541 const auto vectorType =
2542 mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
2543
2544 SmallVector<mlir::Value, 16> elements;
2545 for (Expr *init : e->inits()) {
2546 elements.push_back(Visit(init));
2547 }
2548
2549 // Zero-initialize any remaining values.
2550 if (numInitElements < vectorType.getSize()) {
2551 const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
2552 vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
2553 std::fill_n(std::back_inserter(elements),
2554 vectorType.getSize() - numInitElements, zeroValue);
2555 }
2556
2557 return cir::VecCreateOp::create(cgf.getBuilder(),
2558 cgf.getLoc(e->getSourceRange()), vectorType,
2559 elements);
2560 }
2561
2562 // C++11 value-initialization for the scalar.
2563 if (numInitElements == 0)
2564 return emitNullValue(e->getType(), cgf.getLoc(e->getExprLoc()));
2565
2566 return Visit(e->getInit(0));
2567}
2568
2569mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
2570 QualType srcTy, QualType dstTy,
2571 SourceLocation loc) {
2574 "Invalid scalar expression to emit");
2575 return ScalarExprEmitter(*this, builder)
2576 .emitScalarConversion(src, srcTy, dstTy, loc);
2577}
2578
2580 QualType srcTy,
2581 QualType dstTy,
2582 SourceLocation loc) {
2583 assert(srcTy->isAnyComplexType() && hasScalarEvaluationKind(dstTy) &&
2584 "Invalid complex -> scalar conversion");
2585
2586 QualType complexElemTy = srcTy->castAs<ComplexType>()->getElementType();
2587 if (dstTy->isBooleanType()) {
2588 auto kind = complexElemTy->isFloatingType()
2589 ? cir::CastKind::float_complex_to_bool
2590 : cir::CastKind::int_complex_to_bool;
2591 return builder.createCast(getLoc(loc), kind, src, convertType(dstTy));
2592 }
2593
2594 auto kind = complexElemTy->isFloatingType()
2595 ? cir::CastKind::float_complex_to_real
2596 : cir::CastKind::int_complex_to_real;
2597 mlir::Value real =
2598 builder.createCast(getLoc(loc), kind, src, convertType(complexElemTy));
2599 return emitScalarConversion(real, complexElemTy, dstTy, loc);
2600}
2601
2602mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
2603 // Perform vector logical not on comparison with zero vector.
2604 if (e->getType()->isVectorType() &&
2605 e->getType()->castAs<VectorType>()->getVectorKind() ==
2607 mlir::Value oper = Visit(e->getSubExpr());
2608 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2609 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2610 auto exprVecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
2611 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2612 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2613 oper, zeroVec);
2614 }
2615
2616 // Compare operand to zero.
2617 mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());
2618
2619 // Invert value.
2620 boolVal = builder.createNot(boolVal);
2621
2622 // ZExt result to the expr type.
2623 return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
2624}
2625
2626mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {
2627 // Try folding the offsetof to a constant.
2628 Expr::EvalResult evalResult;
2629 if (e->EvaluateAsInt(evalResult, cgf.getContext())) {
2630 mlir::Type type = cgf.convertType(e->getType());
2631 llvm::APSInt value = evalResult.Val.getInt();
2632 return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);
2633 }
2634
2636 e->getSourceRange(),
2637 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2638 return {};
2639}
2640
2641mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
2642 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
2643 mlir::Value result = VisitRealImag(e, promotionTy);
2644 if (result && !promotionTy.isNull())
2645 result = emitUnPromotedValue(result, e->getType());
2646 return result;
2647}
2648
2649mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {
2650 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
2651 mlir::Value result = VisitRealImag(e, promotionTy);
2652 if (result && !promotionTy.isNull())
2653 result = emitUnPromotedValue(result, e->getType());
2654 return result;
2655}
2656
2657mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
2658 QualType promotionTy) {
2659 assert(
2660 (e->getOpcode() == clang::UO_Real || e->getOpcode() == clang::UO_Imag) &&
2661 "Invalid UnaryOp kind for ComplexType Real or Imag");
2662
2663 Expr *op = e->getSubExpr();
2664 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2665 if (op->getType()->isAnyComplexType()) {
2666 // If it's an l-value, load through the appropriate subobject l-value.
2667 // Note that we have to ask `e` because `op` might be an l-value that
2668 // this won't work for, e.g. an Obj-C property
2669 mlir::Value complex = cgf.emitComplexExpr(op);
2670 if (e->isGLValue() && !promotionTy.isNull()) {
2671 promotionTy = promotionTy->isAnyComplexType()
2672 ? promotionTy
2673 : cgf.getContext().getComplexType(promotionTy);
2674 complex = cgf.emitPromotedValue(complex, promotionTy);
2675 }
2676
2677 return e->getOpcode() == clang::UO_Real
2678 ? builder.createComplexReal(loc, complex)
2679 : builder.createComplexImag(loc, complex);
2680 }
2681
2682 if (e->getOpcode() == UO_Real) {
2683 mlir::Value operand = promotionTy.isNull()
2684 ? Visit(op)
2685 : cgf.emitPromotedScalarExpr(op, promotionTy);
2686 return builder.createComplexReal(loc, operand);
2687 }
2688
2689 // __imag on a scalar returns zero. Emit the subexpr to ensure side
2690 // effects are evaluated, but not the actual value.
2691 mlir::Value operand;
2692 if (op->isGLValue()) {
2693 operand = cgf.emitLValue(op).getPointer();
2694 operand = cir::LoadOp::create(builder, loc, operand);
2695 } else if (!promotionTy.isNull()) {
2696 operand = cgf.emitPromotedScalarExpr(op, promotionTy);
2697 } else {
2698 operand = cgf.emitScalarExpr(op);
2699 }
2700 return builder.createComplexImag(loc, operand);
2701}
2702
2703/// Return the size or alignment of the type of argument of the sizeof
2704/// expression as an integer.
2705mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2706 const UnaryExprOrTypeTraitExpr *e) {
2707 const QualType typeToSize = e->getTypeOfArgument();
2708 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
2709 if (auto kind = e->getKind();
2710 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
2711 if (const VariableArrayType *vat =
2712 cgf.getContext().getAsVariableArrayType(typeToSize)) {
2713 // For _Countof, we only want to evaluate if the extent is actually
2714 // variable as opposed to a multi-dimensional array whose extent is
2715 // constant but whose element type is variable.
2716 bool evaluateExtent = true;
2717 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2718 evaluateExtent =
2719 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.getContext());
2720 }
2721
2722 if (evaluateExtent) {
2723 if (e->isArgumentType()) {
2724 // sizeof(type) - make sure to emit the VLA size.
2725 cgf.emitVariablyModifiedType(typeToSize);
2726 } else {
2727 // C99 6.5.3.4p2: If the argument is an expression of type
2728 // VLA, it is evaluated.
2730 }
2731
2732 // For _Countof, we just want to return the size of a single dimension.
2733 if (kind == UETT_CountOf)
2734 return cgf.getVLAElements1D(vat).numElts;
2735
2736 // For sizeof and __datasizeof, we need to scale the number of elements
2737 // by the size of the array element type.
2738 CIRGenFunction::VlaSizePair vlaSize = cgf.getVLASize(vat);
2739 mlir::Value numElts = vlaSize.numElts;
2740
2741 // Scale the number of non-VLA elements by the non-VLA element size.
2742 CharUnits eltSize = cgf.getContext().getTypeSizeInChars(vlaSize.type);
2743 if (!eltSize.isOne()) {
2744 mlir::Location loc = cgf.getLoc(e->getSourceRange());
2745 mlir::Value eltSizeValue =
2746 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
2747 cgf.cgm.getSize(eltSize).getValue());
2748 return builder.createMul(loc, eltSizeValue, numElts,
2750 }
2751
2752 return numElts;
2753 }
2754 }
2755 } else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
2757 cgf.getContext()
2760 .getQuantity();
2761 return builder.getConstantInt(loc, cgf.cgm.sizeTy, alignment);
2762 } else if (e->getKind() == UETT_VectorElements) {
2763 auto vecTy = cast<cir::VectorType>(convertType(e->getTypeOfArgument()));
2764 if (vecTy.getIsScalable()) {
2766 e->getSourceRange(),
2767 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2768 return builder.getConstant(
2769 loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,
2771 }
2772
2773 return builder.getConstant(
2774 loc, cir::IntAttr::get(cgf.cgm.uInt64Ty, vecTy.getSize()));
2775 }
2776
2777 return builder.getConstant(
2778 loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,
2780}
2781
2782/// Return true if the specified expression is cheap enough and side-effect-free
2783/// enough to evaluate unconditionally instead of conditionally. This is used
2784/// to convert control flow into selects in some cases.
2785/// TODO(cir): can be shared with LLVM codegen.
2787 CIRGenFunction &cgf) {
2788 // Anything that is an integer or floating point constant is fine.
2789 return e->IgnoreParens()->isEvaluatable(cgf.getContext());
2790
2791 // Even non-volatile automatic variables can't be evaluated unconditionally.
2792 // Referencing a thread_local may cause non-trivial initialization work to
2793 // occur. If we're inside a lambda and one of the variables is from the scope
2794 // outside the lambda, that function may have returned already. Reading its
2795 // locals is a bad idea. Also, these reads may introduce races there didn't
2796 // exist in the source-level program.
2797}
2798
2799mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2800 const AbstractConditionalOperator *e) {
2801 CIRGenBuilderTy &builder = cgf.getBuilder();
2802 mlir::Location loc = cgf.getLoc(e->getSourceRange());
2803 ignoreResultAssign = false;
2804
2805 // Bind the common expression if necessary.
2806 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2807
2808 Expr *condExpr = e->getCond();
2809 Expr *lhsExpr = e->getTrueExpr();
2810 Expr *rhsExpr = e->getFalseExpr();
2811
2812 // If the condition constant folds and can be elided, try to avoid emitting
2813 // the condition and the dead arm.
2814 bool condExprBool;
2815 if (cgf.constantFoldsToBool(condExpr, condExprBool)) {
2816 Expr *live = lhsExpr, *dead = rhsExpr;
2817 if (!condExprBool)
2818 std::swap(live, dead);
2819
2820 // If the dead side doesn't have labels we need, just emit the Live part.
2821 if (!cgf.containsLabel(dead)) {
2822 if (condExprBool)
2824 mlir::Value result = Visit(live);
2825
2826 // If the live part is a throw expression, it acts like it has a void
2827 // type, so evaluating it returns a null Value. However, a conditional
2828 // with non-void type must return a non-null Value.
2829 if (!result && !e->getType()->isVoidType()) {
2830 result = builder.getConstant(
2831 loc, cir::PoisonAttr::get(builder.getContext(),
2832 cgf.convertType(e->getType())));
2833 }
2834
2835 return result;
2836 }
2837 }
2838
2839 QualType condType = condExpr->getType();
2840
2841 // OpenCL: If the condition is a vector, we can treat this condition like
2842 // the select function.
2843 if (cgf.getLangOpts().OpenCL &&
2844 (condType->isVectorType() || condType->isExtVectorType())) {
2846
2847 mlir::Value condValue = cgf.emitScalarExpr(condExpr);
2848 mlir::Value lhsValue = Visit(lhsExpr);
2849 mlir::Value rhsValue = Visit(rhsExpr);
2850
2851 mlir::Type vecTy = convertType(condType);
2852 mlir::Value zeroVec = builder.getNullValue(vecTy, loc);
2853 auto testMSB = cir::VecCmpOp::create(
2854 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2855 mlir::Value tmp = builder.createIntCast(testMSB, vecTy);
2856 mlir::Value tmp2 = builder.createNot(tmp);
2857
2858 // Cast float to int to perform ANDs if necessary.
2859 mlir::Value rhsTmp = rhsValue;
2860 mlir::Value lhsTmp = lhsValue;
2861 bool wasCast = false;
2862 auto rhsVecTy = cast<cir::VectorType>(rhsValue.getType());
2863 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2864 rhsTmp = builder.createBitcast(rhsValue, tmp2.getType());
2865 lhsTmp = builder.createBitcast(lhsValue, tmp.getType());
2866 wasCast = true;
2867 }
2868
2869 mlir::Value tmp3 = builder.createAnd(loc, rhsTmp, tmp2);
2870 mlir::Value tmp4 = builder.createAnd(loc, lhsTmp, tmp);
2871 mlir::Value tmp5 = builder.createOr(loc, tmp3, tmp4);
2872 if (wasCast)
2873 tmp5 = builder.createBitcast(tmp5, rhsValue.getType());
2874 return tmp5;
2875 }
2876
2877 if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {
2878 if (!condType->isVectorType()) {
2880 cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");
2881 return {};
2882 }
2883
2884 mlir::Value condValue = Visit(condExpr);
2885 mlir::Value lhsValue = Visit(lhsExpr);
2886 mlir::Value rhsValue = Visit(rhsExpr);
2887 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2888 rhsValue);
2889 }
2890
2891 // If this is a really simple expression (like x ? 4 : 5), emit this as a
2892 // select instead of as control flow. We can only do this if it is cheap
2893 // and safe to evaluate the LHS and RHS unconditionally.
2894 if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&
2896 bool lhsIsVoid = false;
2897 mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
2899
2900 mlir::Value lhs = Visit(lhsExpr);
2901 if (!lhs) {
2902 lhs = builder.getNullValue(cgf.voidTy, loc);
2903 lhsIsVoid = true;
2904 }
2905
2906 mlir::Value rhs = Visit(rhsExpr);
2907 if (lhsIsVoid) {
2908 assert(!rhs && "lhs and rhs types must match");
2909 rhs = builder.getNullValue(cgf.voidTy, loc);
2910 }
2911
2912 return builder.createSelect(loc, condV, lhs, rhs);
2913 }
2914
2915 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);
2916 CIRGenFunction::ConditionalEvaluation eval(cgf);
2917 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2918 mlir::Type yieldTy{};
2919
2920 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {
2921 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2923
2924 mlir::Value branch;
2925 {
2926 // Emit any cleanups that were needed on this branch so we can spill
2927 // and reload the return value.
2928 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
2930 eval.beginEvaluation();
2931 branch = Visit(expr);
2932 eval.endEvaluation();
2933 branchCleanups.forceCleanup({&branch});
2934 }
2935
2936 if (branch) {
2937 yieldTy = branch.getType();
2938 cir::YieldOp::create(b, loc, branch);
2939 } else {
2940 // If LHS or RHS is a throw or void expression we need to patch
2941 // arms as to properly match yield types.
2942 insertPoints.push_back(b.saveInsertionPoint());
2943 }
2944 };
2945
2946 mlir::Value result = cir::TernaryOp::create(
2947 builder, loc, condV,
2948 /*trueBuilder=*/
2949 [&](mlir::OpBuilder &b, mlir::Location loc) {
2950 emitBranch(b, loc, lhsExpr);
2951 },
2952 /*falseBuilder=*/
2953 [&](mlir::OpBuilder &b, mlir::Location loc) {
2954 emitBranch(b, loc, rhsExpr);
2955 })
2956 .getResult();
2957
2958 if (!insertPoints.empty()) {
2959 // If both arms are void, so be it.
2960 if (!yieldTy)
2961 yieldTy = cgf.voidTy;
2962
2963 // Insert required yields.
2964 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2965 mlir::OpBuilder::InsertionGuard guard(builder);
2966 builder.restoreInsertionPoint(toInsert);
2967
2968 // Block does not return: build empty yield.
2969 if (mlir::isa<cir::VoidType>(yieldTy)) {
2970 cir::YieldOp::create(builder, loc);
2971 } else { // Block returns: set null yield value.
2972 mlir::Value op0 = builder.getNullValue(yieldTy, loc);
2973 cir::YieldOp::create(builder, loc, op0);
2974 }
2975 }
2976 }
2977
2978 return result;
2979}
2980
2982 LValue lv) {
2983 return ScalarExprEmitter(*this, builder).emitScalarPrePostIncDec(e, lv);
2984}
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
#define HANDLE_BINOP(OP)
static bool mustVisitNullValue(const Expr *e)
#define COMPOUND_OP(Op)
#define HANDLEBINOP(OP)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
#define VISITCOMP(CODE)
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
APSInt & getInt()
Definition APValue.h:508
bool isNullPointer() const
Definition APValue.cpp:1037
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
CanQualType FloatTy
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
CanQualType BoolTy
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h: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:2212
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::Location loc, mlir::Value value, bool nsw=false)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
bool getValue() const
Definition ExprCXX.h:744
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1112
bool getValue() const
Definition ExprCXX.h:4332
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:308
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1609
CastKind getCastKind() const
Definition Expr.h: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:1957
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:3339
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:3095
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3079
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
Definition Expr.h: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:3717
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:248
SourceRange getSourceRange() const
Definition ExprObjC.h:1753
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:190
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:415
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h: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:3392
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1453
QualType getCanonicalType() const
Definition TypeBase.h:8499
bool UseExcessPrecision(const ASTContext &Ctx)
Definition Type.cpp:1662
bool isCanonical() const
Definition TypeBase.h:8504
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:361
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:350
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:364
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:367
bool isSatisfied() const
Whether or not the requires clause is satisfied.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Definition Expr.h: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:2289
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:9050
bool isBooleanType() const
Definition TypeBase.h:9187
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2290
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2267
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantMatrixType() const
Definition TypeBase.h:8851
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9094
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9344
bool isReferenceType() const
Definition TypeBase.h:8708
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition Type.cpp:1959
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
Definition Type.cpp:2702
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:790
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2377
bool isExtVectorType() const
Definition TypeBase.h:8827
bool isExtVectorBoolType() const
Definition TypeBase.h:8831
bool isAnyComplexType() const
Definition TypeBase.h:8819
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition TypeBase.h:9110
bool isHalfType() const
Definition TypeBase.h:9054
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2311
bool isMatrixType() const
Definition TypeBase.h:8847
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2864
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8769
bool isVectorType() const
Definition TypeBase.h:8823
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2406
bool isFloatingType() const
Definition Type.cpp:2390
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:2333
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
bool isNullPtrType() const
Definition TypeBase.h:9087
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2697
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2660
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2247
SourceLocation getExprLoc() const
Definition Expr.h:2371
Expr * getSubExpr() const
Definition Expr.h:2288
Opcode getOpcode() const
Definition Expr.h:2283
static bool isIncrementOp(Opcode Op)
Definition Expr.h:2329
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2322
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Definition Expr.h:2301
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4030
Represents a GCC generic vector type.
Definition TypeBase.h:4239
VectorKind getVectorKind() const
Definition TypeBase.h:4259
OverflowBehavior
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Type
The name was classified as a type.
Definition Sema.h:564
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
Definition TypeBase.h:4200
U cast(CodeGen::Address addr)
Definition Address.h:327
long int64_t
#define false
Definition stdbool.h:26
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool fixedPointType()
static bool vecTernaryOp()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h: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