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