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