clang 24.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
15#include "CIRGenFunction.h"
16#include "CIRGenValue.h"
17
18#include "clang/AST/Expr.h"
23
24#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
25#include "mlir/IR/Location.h"
26#include "mlir/IR/Value.h"
27
28#include <cassert>
29#include <utility>
30
31using namespace clang;
32using namespace clang::CIRGen;
33
34namespace {
35
36struct BinOpInfo {
37 mlir::Value lhs;
38 mlir::Value rhs;
39 SourceRange loc;
40 QualType fullType; // Type of operands and result
41 QualType compType; // Type used for computations. Element type
42 // for vectors, otherwise same as FullType.
43 BinaryOperator::Opcode opcode; // Opcode of BinOp to perform
44 FPOptions fpFeatures;
45 const Expr *e; // Entire expr, for error unsupported. May not be binop.
46
47 /// Check if the binop computes a division or a remainder.
48 bool isDivRemOp() const {
49 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
50 opcode == BO_RemAssign;
51 }
52
53 /// Check if the binop can result in integer overflow.
54 bool mayHaveIntegerOverflow() const {
55 // Without constant input, we can't rule out overflow.
56 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
57 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
58 if (!lhsci || !rhsci)
59 return true;
60
62 // TODO(cir): For now we just assume that we might overflow
63 return true;
64 }
65
66 /// Check if at least one operand is a fixed point type. In such cases,
67 /// this operation did not follow usual arithmetic conversion and both
68 /// operands might not be of the same type.
69 bool isFixedPointOp() const {
70 // We cannot simply check the result type since comparison operations
71 // return an int.
72 if (const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
73 QualType lhstype = binOp->getLHS()->getType();
74 QualType rhstype = binOp->getRHS()->getType();
75 return lhstype->isFixedPointType() || rhstype->isFixedPointType();
76 }
77 if (const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
78 return unop->getSubExpr()->getType()->isFixedPointType();
79 return false;
80 }
81};
82
83class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
84 CIRGenFunction &cgf;
85 CIRGenBuilderTy &builder;
86 // Unlike classic codegen we set this to false or use std::exchange to read
87 // the value instead of calling TestAndClearIgnoreResultAssign to make it
88 // explicit when the value is used
89 bool ignoreResultAssign;
90
91public:
92 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
93 bool ignoreResultAssign = false)
94 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
95
96 //===--------------------------------------------------------------------===//
97 // Utilities
98 //===--------------------------------------------------------------------===//
99 mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }
100
101 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
102 mlir::Value value, CastKind kind,
103 QualType destTy);
104
105 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
106 return cgf.cgm.emitNullConstant(ty, loc);
107 }
108
109 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
110 return builder.createFloatingCast(result, cgf.convertType(promotionType));
111 }
112
113 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
114 return builder.createFloatingCast(result, cgf.convertType(exprType));
115 }
116
117 mlir::Value emitPromoted(const Expr *e, QualType promotionType);
118
119 mlir::Value maybePromoteBoolResult(mlir::Value value,
120 mlir::Type dstTy) const {
121 if (mlir::isa<cir::IntType>(dstTy))
122 return builder.createBoolToInt(value, dstTy);
123 if (mlir::isa<cir::BoolType>(dstTy))
124 return value;
125 llvm_unreachable("Can only promote integer or boolean types");
126 }
127
128 //===--------------------------------------------------------------------===//
129 // Visitor Methods
130 //===--------------------------------------------------------------------===//
131
132 mlir::Value Visit(Expr *e) {
133 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
134 }
135
136 mlir::Value VisitStmt(Stmt *s) {
137 llvm_unreachable("Statement passed to ScalarExprEmitter");
138 }
139
140 mlir::Value VisitExpr(Expr *e) {
141 cgf.getCIRGenModule().errorNYI(
142 e->getSourceRange(), "scalar expression kind: ", e->getStmtClassName());
143 return {};
144 }
145
146 mlir::Value VisitConstantExpr(ConstantExpr *e) {
147 // A constant expression of type 'void' generates no code and produces no
148 // value.
149 if (e->getType()->isVoidType())
150 return {};
151
152 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
153 if (e->isGLValue()) {
154 cgf.cgm.errorNYI(e->getSourceRange(),
155 "ScalarExprEmitter: constant expr GL Value");
156 return {};
157 }
158
159 return builder.getConstant(cgf.getLoc(e->getSourceRange()),
160 mlir::cast<mlir::TypedAttr>(result));
161 }
162
163 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: constant expr");
164 return {};
165 }
166
167 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
168 return Visit(e->getSelectedExpr());
169 }
170
171 mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
172
173 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
174 return Visit(ge->getResultExpr());
175 }
176
177 /// Emits the address of the l-value, then loads and returns the result.
178 mlir::Value emitLoadOfLValue(const Expr *e) {
179 LValue lv = cgf.emitLValue(e);
180 // FIXME: add some akin to EmitLValueAlignmentAssumption(E, V);
181 return cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
182 }
183
184 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
185 return cgf.emitCoawaitExpr(*s).getValue();
186 }
187
188 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
189 return cgf.emitCoyieldExpr(*e).getValue();
190 }
191
192 mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
193 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: unary coawait");
194 return {};
195 }
196
197 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
198 return cgf.emitLoadOfLValue(lv, loc).getValue();
199 }
200
201 // l-values
202 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
203 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
204 return cgf.emitScalarConstant(constant, e);
205
206 return emitLoadOfLValue(e);
207 }
208
209 mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) {
210 auto func = cast<cir::FuncOp>(cgf.curFn);
211 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
212 &cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName());
213 // GotoSolver collects this cir.block_address op after FlattenCFG to keep
214 // the label and wire it as an indirect-branch successor.
215 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->getSourceRange()),
216 cgf.convertType(e->getType()),
217 blockInfoAttr);
218 }
219
220 mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {
221 mlir::Type type = cgf.convertType(e->getType());
222 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
223 cir::IntAttr::get(type, e->getValue()));
224 }
225
226 mlir::Value VisitFixedPointLiteral(const FixedPointLiteral *e) {
227 mlir::Type type = cgf.convertType(e->getType());
228 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
229 cir::IntAttr::get(type, e->getValue()));
230 }
231
232 mlir::Value VisitFloatingLiteral(const FloatingLiteral *e) {
233 mlir::Type type = cgf.convertType(e->getType());
234 assert(mlir::isa<cir::FPTypeInterface>(type) &&
235 "expect floating-point type");
236 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
237 cir::FPAttr::get(type, e->getValue()));
238 }
239
240 mlir::Value VisitCharacterLiteral(const CharacterLiteral *e) {
241 mlir::Type ty = cgf.convertType(e->getType());
242 // Character literals are always stored in an unsigned (even for signed
243 // char), so allow implicit truncation here.
244 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
245 llvm::APInt apValue(intTy.getWidth(), e->getValue(),
246 /*isSigned=*/false, /*implicitTrunc=*/true);
247 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
248 cir::IntAttr::get(ty, apValue));
249 }
250
251 mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {
252 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
253 }
254
255 mlir::Value VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *e) {
256 if (e->getType()->isVoidType())
257 return {};
258
259 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
260 }
261
262 mlir::Value VisitGNUNullExpr(const GNUNullExpr *e) {
263 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
264 }
265
266 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
267
268 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
269 return builder.getConstInt(cgf.getLoc(e->getExprLoc()),
270 convertType(e->getType()), e->getPackLength());
271 }
272 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
273 return cgf.emitPseudoObjectRValue(e).getValue();
274 }
275 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e);
276 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
277 assert(e->getDataElementCount() == 1);
278 auto it = e->begin();
279 llvm::APInt value = (*it)->getValue();
280 return builder.getConstInt(cgf.getLoc(e->getExprLoc()), value,
282 }
283 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
284 if (e->isGLValue())
285 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
286 e->getExprLoc());
287
288 // Otherwise, assume the mapping is the scalar directly.
289 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
290 }
291
292 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
293 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc selector");
294 return {};
295 }
296 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
297 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc protocol");
298 return {};
299 }
300 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
301 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc ivar ref");
302 return {};
303 }
304 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
305 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc message");
306 return {};
307 }
308 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
309 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc isa");
310 return {};
311 }
312 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
313 cgf.cgm.errorNYI(e->getSourceRange(),
314 "ScalarExprEmitter: objc availability check");
315 return {};
316 }
317
318 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
319 mlir::Value rowIdx = cgf.emitScalarExpr(e->getRowIdx());
320 mlir::Value columnIdx = cgf.emitScalarExpr(e->getColumnIdx());
321 mlir::Value matrix = Visit(e->getBase());
322 mlir::Location loc = cgf.getLoc(e->getSourceRange());
323 if (cgf.cgm.getCodeGenOpts().OptimizationLevel > 0)
325 return builder.createMatrixExtract(loc, matrix, rowIdx, columnIdx);
326 }
327
328 mlir::Value VisitMatrixSingleSubscriptExpr(MatrixSingleSubscriptExpr *e) {
329 cgf.cgm.errorNYI(e->getSourceRange(),
330 "ScalarExprEmitter: matrix singel subscript");
331 return {};
332 }
333
334 mlir::Value VisitCastExpr(CastExpr *e);
335 mlir::Value VisitCallExpr(const CallExpr *e);
336
337 mlir::Value VisitStmtExpr(StmtExpr *e) {
338 CIRGenFunction::StmtExprEvaluation eval(cgf);
339 if (e->getType()->isVoidType()) {
340 (void)cgf.emitCompoundStmt(*e->getSubStmt());
341 return {};
342 }
343
344 Address retAlloca =
345 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
346 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
347
348 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->getType()),
349 e->getExprLoc());
350 }
351
352 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
353 ignoreResultAssign = false;
354
355 if (e->getBase()->getType()->isVectorType()) {
357
358 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
359 const mlir::Value vecValue = Visit(e->getBase());
360 const mlir::Value indexValue = Visit(e->getIdx());
361 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
362 }
363 // Just load the lvalue formed by the subscript expression.
364 return emitLoadOfLValue(e);
365 }
366
367 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
368 if (e->getNumSubExprs() == 2) {
369 // The undocumented form of __builtin_shufflevector.
370 mlir::Value inputVec = Visit(e->getExpr(0));
371 mlir::Value indexVec = Visit(e->getExpr(1));
372 return cir::VecShuffleDynamicOp::create(
373 cgf.builder, cgf.getLoc(e->getSourceRange()), inputVec, indexVec);
374 }
375
376 mlir::Value vec1 = Visit(e->getExpr(0));
377 mlir::Value vec2 = Visit(e->getExpr(1));
378
379 // The documented form of __builtin_shufflevector, where the indices are
380 // a variable number of integer constants. The constants will be stored
381 // in an ArrayAttr.
382 SmallVector<mlir::Attribute, 8> indices;
383 for (unsigned i = 2; i < e->getNumSubExprs(); ++i) {
384 indices.push_back(
385 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
386 e->getExpr(i)
387 ->EvaluateKnownConstInt(cgf.getContext())
388 .getSExtValue()));
389 }
390
391 return cir::VecShuffleOp::create(cgf.builder,
392 cgf.getLoc(e->getSourceRange()),
393 cgf.convertType(e->getType()), vec1, vec2,
394 cgf.builder.getArrayAttr(indices));
395 }
396
397 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
398 // __builtin_convertvector is an element-wise cast, and is implemented as a
399 // regular cast. The back end handles casts of vectors correctly.
400 return emitScalarConversion(Visit(e->getSrcExpr()),
401 e->getSrcExpr()->getType(), e->getType(),
402 e->getSourceRange().getBegin());
403 }
404
405 mlir::Value VisitExtVectorElementExpr(Expr *e) { return emitLoadOfLValue(e); }
406
407 mlir::Value VisitMatrixElementExpr(Expr *e) {
408 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: matrix element");
409 return {};
410 }
411
412 mlir::Value VisitMemberExpr(MemberExpr *e);
413
414 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
415 return emitLoadOfLValue(e);
416 }
417
418 mlir::Value VisitInitListExpr(InitListExpr *e);
419
420 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
421 assert(cgf.getArrayInitIndex() &&
422 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
423 return cgf.getArrayInitIndex();
424 }
425
426 mlir::Value VisitImplicitValueInitExpr(const ImplicitValueInitExpr *e) {
427 return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
428 }
429
430 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
431 return VisitCastExpr(e);
432 }
433
434 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
435 return cgf.cgm.emitNullConstant(e->getType(),
436 cgf.getLoc(e->getSourceRange()));
437 }
438
439 /// Perform a pointer to boolean conversion.
440 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
441 // TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM.
442 // We might want to have a separate pass for these types of conversions.
443 return cgf.getBuilder().createPtrToBoolCast(v);
444 }
445
446 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
447 cir::BoolType boolTy = builder.getBoolTy();
448 return cir::CastOp::create(builder, loc, boolTy,
449 cir::CastKind::float_to_bool, src);
450 }
451
452 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
453 // The enumerator of an enum with an integral underlying type is lowered to
454 // that type, which can be bool. In that case the operand is already a
455 // !cir.bool, so return it -- int_to_bool requires a !cir.int source.
456 if (mlir::isa<cir::BoolType>(srcVal.getType()))
457 return srcVal;
458
459 // Because of the type rules of C, we often end up computing a
460 // logical value, then zero extending it to int, then wanting it
461 // as a logical value again.
462 // TODO: optimize this common case here or leave it for later
463 // CIR passes?
464 cir::BoolType boolTy = builder.getBoolTy();
465 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
466 srcVal);
467 }
468
469 /// Convert the specified expression value to a boolean (!cir.bool) truth
470 /// value. This is equivalent to "Val != 0".
471 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
472 mlir::Location loc) {
473 assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs");
474
475 if (srcType->isRealFloatingType())
476 return emitFloatToBoolConversion(src, loc);
477
478 if (llvm::isa<MemberPointerType>(srcType)) {
479 cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion");
480 return builder.getFalse(loc);
481 }
482
483 if (srcType->isIntegerType())
484 return emitIntToBoolConversion(src, loc);
485
486 assert(::mlir::isa<cir::PointerType>(src.getType()));
487 return emitPointerToBoolConversion(src, srcType);
488 }
489
490 // Emit a conversion from the specified type to the specified destination
491 // type, both of which are CIR scalar types.
492 struct ScalarConversionOpts {
493 bool treatBooleanAsSigned;
494 bool emitImplicitIntegerTruncationChecks;
495 bool emitImplicitIntegerSignChangeChecks;
496
497 ScalarConversionOpts()
498 : treatBooleanAsSigned(false),
499 emitImplicitIntegerTruncationChecks(false),
500 emitImplicitIntegerSignChangeChecks(false) {}
501
502 ScalarConversionOpts(clang::SanitizerSet sanOpts)
503 : treatBooleanAsSigned(false),
504 emitImplicitIntegerTruncationChecks(
505 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
506 emitImplicitIntegerSignChangeChecks(
507 sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
508 };
509
510 // Conversion from bool, integral, or floating-point to integral or
511 // floating-point. Conversions involving other types are handled elsewhere.
512 // Conversion to bool is handled elsewhere because that's a comparison against
513 // zero, not a simple cast. This handles both individual scalars and vectors.
514 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
515 QualType dstType, mlir::Type srcTy,
516 mlir::Type dstTy, ScalarConversionOpts opts) {
517 assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
518 "Internal error: matrix types not handled by this function.");
519 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
520 mlir::isa<mlir::IntegerType>(dstTy)) &&
521 "Obsolete code. Don't use mlir::IntegerType with CIR.");
522
523 mlir::Type fullDstTy = dstTy;
524 if (mlir::isa<cir::VectorType>(srcTy) &&
525 mlir::isa<cir::VectorType>(dstTy)) {
526 // Use the element types of the vectors to figure out the CastKind.
527 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
528 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
529 }
530
531 std::optional<cir::CastKind> castKind;
532
533 // Start with a null fenv attr. If this is a floating point cast, we will
534 // get the attribute from the builder.
535 cir::FenvAttr fenvAttr;
536
537 if (mlir::isa<cir::BoolType>(srcTy)) {
538 if (opts.treatBooleanAsSigned)
539 cgf.getCIRGenModule().errorNYI("signed bool");
540 if (cgf.getBuilder().isInt(dstTy)) {
541 castKind = cir::CastKind::bool_to_int;
542 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
543 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
544 castKind = cir::CastKind::bool_to_float;
545 } else {
546 llvm_unreachable("Internal error: Cast to unexpected type");
547 }
548 } else if (cgf.getBuilder().isInt(srcTy)) {
549 if (cgf.getBuilder().isInt(dstTy)) {
550 castKind = cir::CastKind::integral;
551 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
552 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
553 castKind = cir::CastKind::int_to_float;
554 } else if (mlir::isa<cir::BoolType>(dstTy)) {
555 castKind = cir::CastKind::int_to_bool;
556 } else {
557 llvm_unreachable("Internal error: Cast to unexpected type");
558 }
559 } else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
560 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
561 if (cgf.getBuilder().isInt(dstTy)) {
562 // If we can't recognize overflow as undefined behavior, assume that
563 // overflow saturates. This protects against normal optimizations if we
564 // are compiling with non-standard FP semantics.
565 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
566 cgf.getCIRGenModule().errorNYI("strict float cast overflow");
567 castKind = cir::CastKind::float_to_int;
568 } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
569 // TODO: split this to createFPExt/createFPTrunc
570 return builder.createFloatingCast(src, fullDstTy);
571 } else if (mlir::isa<cir::BoolType>(dstTy)) {
572 castKind = cir::CastKind::float_to_bool;
573 } else {
574 llvm_unreachable("Internal error: Cast to unexpected type");
575 }
576 } else {
577 llvm_unreachable("Internal error: Cast from unexpected type");
578 }
579
580 assert(castKind.has_value() && "Internal error: CastKind not set.");
581 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
582 src, fenvAttr);
583 }
584
585 mlir::Value
586 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
587 return Visit(e->getReplacement());
588 }
589
590 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
591 QualType ty = ve->getType();
592
593 if (ty->isVariablyModifiedType()) {
594 cgf.cgm.errorNYI(ve->getSourceRange(),
595 "variably modified types in varargs");
596 }
597
598 return cgf.emitVAArg(ve);
599 }
600
601 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
602 return Visit(e->getSemanticForm());
603 }
604
605 mlir::Value VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *e);
606 mlir::Value
607 VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
608
609 // Unary Operators.
610 mlir::Value VisitUnaryPrePostIncDec(const UnaryOperator *e) {
611 LValue lv = cgf.emitLValue(e->getSubExpr());
612 return emitScalarPrePostIncDec(e, lv);
613 }
614 mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
615 return VisitUnaryPrePostIncDec(e);
616 }
617 mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
618 return VisitUnaryPrePostIncDec(e);
619 }
620 mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
621 return VisitUnaryPrePostIncDec(e);
622 }
623 mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
624 return VisitUnaryPrePostIncDec(e);
625 }
626
627 mlir::Value emitFixedPointIncDec(const UnaryOperator *e, mlir::Value value,
628 QualType type);
629 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv) {
630 if (cgf.getLangOpts().OpenMP)
631 cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");
632
633 QualType type = e->getSubExpr()->getType();
634
635 mlir::Value value;
636 mlir::Value input;
637
638 if (const AtomicType *atomicTy = type->getAs<AtomicType>()) {
639 QualType valType = atomicTy->getValueType();
640 mlir::Location loc = cgf.getLoc(e->getSourceRange());
641 bool isInc = e->isIncrementOp();
642 bool isPre = e->isPrefix();
643
644 // Bools are always set-to-true, as decrement isn't legal on bools.
645 if (valType->isBooleanType()) {
646 assert(isInc);
647 // Atomic operations require an integer type; reinterpret the bool
648 // pointer as a pointer to its underlying storage integer type.
649 cir::IntType intTy = builder.getBoolMemoryTy();
650 mlir::Value one = builder.getConstInt(loc, intTy, 1);
651 Address intAddr = lv.getAddress().withElementType(builder, intTy);
652
653 if (isPre) {
654 // Pre-increment: atomically store true, return true.
655 cir::StoreOp store = builder.createStore(loc, one, intAddr);
656 store.setMemOrder(cir::MemOrder::SequentiallyConsistent);
657 if (lv.isVolatileQualified())
658 store.setIsVolatile(true);
659 return builder.getTrue(loc);
660 }
661 // Post-increment: atomically exchange with true, return old value.
662 auto xchg = cir::AtomicXchgOp::create(
663 builder, loc, intAddr.getPointer(), one,
664 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
665 lv.isVolatileQualified());
666 return builder.createCast(cir::CastKind::int_to_bool, xchg.getResult(),
667 builder.getBoolTy());
668 }
669
670 // Special case for atomic increment / decrement on integers, emit
671 // atomicrmw instructions. We skip this if we want to be doing overflow
672 // checking, and fall into the slow path with the atomic cmpxchg loop.
673 if (valType->isIntegerType() &&
674 !(valType->isUnsignedIntegerType() &&
675 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) &&
676 cgf.getLangOpts().getSignedOverflowBehavior() !=
677 LangOptions::SOB_Trapping) {
678 mlir::Type intTy = cgf.convertType(valType);
679 mlir::Value one = builder.getConstInt(loc, intTy, 1);
680 cir::AtomicFetchKind kind =
681 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
682 auto rmw = cir::AtomicFetchOp::create(
683 builder, loc, lv.getPointer(), one, kind,
684 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
685 lv.isVolatileQualified(), /*fetch_first=*/true);
686 mlir::Value oldVal = rmw->getResult(0);
687 // Prefix returns new value; postfix returns old value.
688 return isPre ? emitIntIncOrDec(e, oldVal) : oldVal;
689 }
690
691 // Special case for atomic increment/decrement on floats.
692 // Bail out non-power-of-2-sized floating point types (e.g., x86_fp80).
693 if (valType->isFloatingType()) {
694 mlir::Type fpTy = cgf.convertType(valType);
695 auto fpType = mlir::cast<cir::FPTypeInterface>(fpTy);
696 // Bail on non-power-of-2 types (e.g., x86_fp80 is 80 bits).
697 if (llvm::has_single_bit(fpType.getWidth())) {
698 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
699 mlir::Value amt = builder.getConstFP(
700 loc, fpTy, llvm::APFloat(fpType.getFloatSemantics(), 1));
701 cir::AtomicFetchKind kind =
702 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
703 auto rmw = cir::AtomicFetchOp::create(
704 builder, loc, lv.getPointer(), amt, kind,
705 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
706 lv.isVolatileQualified(), /*fetch_first=*/true);
707 mlir::Value oldVal = rmw->getResult(0);
708 if (isPre)
709 return isInc ? builder.createFAdd(loc, oldVal, amt)
710 : builder.createFSub(loc, oldVal, amt);
711 return oldVal;
712 } else {
713 cgf.cgm.errorNYI(e->getSourceRange(),
714 "Atomic inc/dec of non-power-of-2 float");
715 }
716 }
717
718 // Otherwise we need a loop on compare-exchange.
719 cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");
720 value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
721 input = value;
722 } else {
723 value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
724 input = value;
725 }
726
727 // NOTE: When possible, more frequent cases are handled first.
728
729 // Special case of integer increment that we have to check first: bool++.
730 // Due to promotion rules, we get:
731 // bool++ -> bool = bool + 1
732 // -> bool = (int)bool + 1
733 // -> bool = ((int)bool + 1 != 0)
734 // An interesting aspect of this is that increment is always true.
735 // Decrement does not have this property.
736 if (e->isIncrementOp() && type->isBooleanType()) {
737 value = builder.getTrue(cgf.getLoc(e->getExprLoc()));
738 } else if (type->isIntegerType()) {
739 QualType promotedType;
740 [[maybe_unused]] bool canPerformLossyDemotionCheck = false;
741 if (cgf.getContext().isPromotableIntegerType(type)) {
742 promotedType = cgf.getContext().getPromotedIntegerType(type);
743 assert(promotedType != type && "Shouldn't promote to the same type.");
744 canPerformLossyDemotionCheck = true;
745 canPerformLossyDemotionCheck &=
746 cgf.getContext().getCanonicalType(type) !=
747 cgf.getContext().getCanonicalType(promotedType);
748 canPerformLossyDemotionCheck &=
749 type->isIntegerType() && promotedType->isIntegerType();
750
751 // TODO(cir): Currently, we store bitwidths in CIR types only for
752 // integers. This might also be required for other types.
753
754 assert(
755 (!canPerformLossyDemotionCheck ||
756 type->isSignedIntegerOrEnumerationType() ||
757 promotedType->isSignedIntegerOrEnumerationType() ||
758 mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth() ==
759 mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth()) &&
760 "The following check expects that if we do promotion to different "
761 "underlying canonical type, at least one of the types (either "
762 "base or promoted) will be signed, or the bitwidths will match.");
763 }
764
766 if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
767 value = emitIncDecConsiderOverflowBehavior(e, value);
768 } else {
769 // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
770 value = emitIntIncOrDec(e, input, /*nsw=*/false);
771 }
772 } else if (const PointerType *ptr = type->getAs<PointerType>()) {
773 QualType type = ptr->getPointeeType();
774 if (const VariableArrayType *vla =
775 cgf.getContext().getAsVariableArrayType(type)) {
776 mlir::Location loc = cgf.getLoc(e->getSourceRange());
777 mlir::Value numElts = cgf.getVLASize(vla).numElts;
778 if (!e->isIncrementOp())
779 numElts = cgf.getBuilder().createNeg(loc, numElts, /*nsw=*/true);
781 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
782 } else {
783 // For everything else, we can just do a simple increment.
784 mlir::Location loc = cgf.getLoc(e->getSourceRange());
785 int amount = e->isIncrementOp() ? 1 : -1;
786 mlir::Value amt = builder.getSInt32(amount, loc);
788 value = builder.createPtrStride(loc, value, amt);
789 }
790 } else if (type->isVectorType()) {
791 if (type->hasIntegerRepresentation()) {
792 value = emitIntIncOrDec(e, input, /*nsw=*/false);
793 } else {
794 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
795 value = emitFloatIncOrDec(e, input);
796 }
797 } else if (type->isRealFloatingType()) {
798 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
799 value = emitFloatIncOrDec(e, input);
800 } else if (type->isFixedPointType()) {
801 value = emitFixedPointIncDec(e, value, type);
802 } else {
803 assert(type->castAs<ObjCObjectPointerType>());
804 cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");
805 return {};
806 }
807
808 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->getSourceRange()};
809
810 // Store the updated result through the lvalue
811 if (lv.isBitField())
812 value = cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);
813 else
814 cgf.emitStoreThroughLValue(RValue::get(value), lv);
815
816 // If this is a postinc, return the value read from memory, otherwise use
817 // the updated value.
818 return e->isPrefix() ? value : input;
819 }
820
821 mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,
822 mlir::Value inVal) {
823 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
824 case LangOptions::SOB_Defined:
825 return emitIntIncOrDec(e, inVal, /*nsw=*/false);
826 case LangOptions::SOB_Undefined:
828 return emitIntIncOrDec(e, inVal, /*nsw=*/true);
829 case LangOptions::SOB_Trapping:
830 if (!e->canOverflow())
831 return emitIntIncOrDec(e, inVal, /*nsw=*/true);
832 cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
833 return {};
834 }
835 llvm_unreachable("Unexpected signed overflow behavior kind");
836 }
837
838 mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
839 if (llvm::isa<MemberPointerType>(e->getType()))
840 return cgf.cgm.emitMemberPointerConstant(e);
841
842 return cgf.emitLValue(e->getSubExpr()).getPointer();
843 }
844
845 mlir::Value VisitUnaryDeref(const UnaryOperator *e) {
846 if (e->getType()->isVoidType())
847 return Visit(e->getSubExpr()); // the actual value should be unused
848 return emitLoadOfLValue(e);
849 }
850
851 mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
852 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
853 mlir::Value result = VisitUnaryPlus(e, promotionType);
854 if (result && !promotionType.isNull())
855 return emitUnPromotedValue(result, e->getType());
856 return result;
857 }
858
859 mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType) {
860 ignoreResultAssign = false;
861 if (!promotionType.isNull())
862 return cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
863 return Visit(e->getSubExpr());
864 }
865
866 mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
867 QualType promotionType = getPromotionType(e->getSubExpr()->getType());
868 mlir::Value result = VisitUnaryMinus(e, promotionType);
869 if (result && !promotionType.isNull())
870 return emitUnPromotedValue(result, e->getType());
871 return result;
872 }
873
874 mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType) {
875 ignoreResultAssign = false;
876 mlir::Value operand;
877 if (!promotionType.isNull())
878 operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
879 else
880 operand = Visit(e->getSubExpr());
881
882 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
883
884 if (cir::isFPOrVectorOfFPType(operand.getType()))
885 return builder.createOrFold<cir::FNegOp>(loc, operand);
886
887 // TODO(cir): We might have to change this to support overflow trapping.
888 // Classic codegen routes unary minus through emitSub to ensure
889 // that the overflow behavior is handled correctly.
890 bool nsw = e->getType()->isSignedIntegerType() &&
891 cgf.getLangOpts().getSignedOverflowBehavior() !=
892 LangOptions::SOB_Defined;
893
894 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
895 }
896
897 mlir::Value emitIntIncOrDec(const UnaryOperator *e, mlir::Value input,
898 bool nsw = false) {
899 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
900 return e->isIncrementOp()
901 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
902 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
903 }
904
905 mlir::Value emitFloatIncOrDec(const UnaryOperator *e, mlir::Value input) {
906 assert(cir::isFPOrVectorOfFPType(input.getType()) &&
907 "Expect floating-point operand");
908 mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
909
910 if (auto vecType = mlir::dyn_cast<cir::VectorType>(input.getType())) {
911 mlir::Type fpScalarType = vecType.getElementType();
912 auto fpInterface = mlir::cast<cir::FPTypeInterface>(fpScalarType);
913 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
914 /*Negative=*/e->isDecrementOp());
915 mlir::Value amtValue = builder.getConstFP(loc, fpScalarType, amount);
916 amtValue = cir::VecSplatOp::create(builder, loc, vecType, amtValue);
917 return builder.createFAdd(loc, input, amtValue);
918 }
919
920 QualType type = e->getSubExpr()->getType();
921 // Another special case: half FP increment should be done via float.
922 if (type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
923 input = builder.createFloatingCast(input, builder.getSingleTy());
924
925 auto fpInterface = mlir::cast<cir::FPTypeInterface>(input.getType());
926 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
927 /*Negative=*/e->isDecrementOp());
928 mlir::Value amtValue = builder.getConstFP(loc, input.getType(), amount);
929 mlir::Value output = builder.createFAdd(loc, input, amtValue);
930
931 if (type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
932 output = builder.createFloatingCast(output, builder.getFp16Ty());
933
934 return output;
935 }
936
937 mlir::Value VisitUnaryNot(const UnaryOperator *e) {
938 ignoreResultAssign = false;
939 mlir::Value op = Visit(e->getSubExpr());
940 return builder.createOrFold<cir::NotOp>(
941 cgf.getLoc(e->getSourceRange().getBegin()), op);
942 }
943
944 mlir::Value VisitUnaryLNot(const UnaryOperator *e);
945
946 mlir::Value VisitUnaryReal(const UnaryOperator *e);
947 mlir::Value VisitUnaryImag(const UnaryOperator *e);
948 mlir::Value VisitRealImag(const UnaryOperator *e,
949 QualType promotionType = QualType());
950
951 mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
952 return Visit(e->getSubExpr());
953 }
954
955 // C++
956 mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e) {
957 return emitLoadOfLValue(e);
958 }
959 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
960 ASTContext &ctx = cgf.getContext();
961 APValue evaluated =
962 e->EvaluateInContext(ctx, cgf.curSourceLocExprScope.getDefaultExpr());
963 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
964 e->getLocation(), evaluated, e->getType());
965 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
966 return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
967 typedAttr);
968 }
969 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
970 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
971 return Visit(dae->getExpr());
972 }
973 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
974 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
975 return Visit(die->getExpr());
976 }
977
978 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
979
980 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
981 mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
982 return cgf.emitCXXNewExpr(e);
983 }
984 mlir::Value VisitCXXDeleteExpr(const CXXDeleteExpr *e) {
985 cgf.emitCXXDeleteExpr(e);
986 return {};
987 }
988 mlir::Value VisitTypeTraitExpr(const TypeTraitExpr *e) {
989 // We diverge slightly from classic codegen here because CIR has stricter
990 // typing. In LLVM IR, constant folding covers up some potential type
991 // mismatches such as bool-to-int conversions that would fail the verifier
992 // in CIR. To make things work, we need to be sure we only emit a bool value
993 // if the expression type is bool.
994 mlir::Location loc = cgf.getLoc(e->getExprLoc());
995 if (e->isStoredAsBoolean()) {
996 if (e->getType()->isBooleanType())
997 return builder.getBool(e->getBoolValue(), loc);
998 assert(e->getType()->isIntegerType() &&
999 "Expected int type for TypeTraitExpr");
1000 return builder.getConstInt(loc, cgf.convertType(e->getType()),
1001 (uint64_t)e->getBoolValue());
1002 }
1003 assert(e->getType()->isIntegerType() && "not a scalar type trait");
1004 return builder.getConstInt(loc, e->getAPValue().getInt());
1005 }
1006 mlir::Value
1007 VisitConceptSpecializationExpr(const ConceptSpecializationExpr *e) {
1008 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
1009 }
1010 mlir::Value VisitRequiresExpr(const RequiresExpr *e) {
1011 return builder.getBool(e->isSatisfied(), cgf.getLoc(e->getExprLoc()));
1012 }
1013 mlir::Value VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *e) {
1014 mlir::Type type = cgf.convertType(e->getType());
1015 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1016 return builder.getConstInt(loc, type, e->getValue());
1017 }
1018 mlir::Value VisitExpressionTraitExpr(const ExpressionTraitExpr *e) {
1019 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
1020 }
1021 mlir::Value VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *e) {
1022 cgf.cgm.errorNYI(e->getSourceRange(),
1023 "ScalarExprEmitter: cxx pseudo destructor");
1024 return {};
1025 }
1026 mlir::Value VisitCXXThrowExpr(const CXXThrowExpr *e) {
1027 cgf.emitCXXThrowExpr(e);
1028 return {};
1029 }
1030
1031 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
1032 return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
1033 }
1034
1035 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
1036 QualType dstTy, mlir::Location loc);
1037
1038 /// Emit a conversion from the specified type to the specified destination
1039 /// type, both of which are CIR scalar types.
1040 /// TODO: do we need ScalarConversionOpts here? Should be done in another
1041 /// pass.
1042 mlir::Value
1043 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
1044 SourceLocation loc,
1045 ScalarConversionOpts opts = ScalarConversionOpts()) {
1046 // All conversions involving fixed point types should be handled by the
1047 // emitFixedPoint family functions. This is done to prevent bloating up
1048 // this function more, and although fixed point numbers are represented by
1049 // integers, we do not want to follow any logic that assumes they should be
1050 // treated as integers.
1051 if (srcType->isFixedPointType()) {
1052 if (dstType->isBooleanType()) {
1053 cir::BoolType boolTy = builder.getBoolTy();
1054 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
1055 cir::CastKind::int_to_bool, src);
1056 }
1057
1058 if (dstType->isFixedPointType() || dstType->isIntegerType() ||
1059 dstType->isRealFloatingType())
1060 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1061
1062 llvm_unreachable("Unhandled scalar conversion from a fixed point type to "
1063 "another type.");
1064 } else if (dstType->isFixedPointType()) {
1065 if (srcType->isIntegerType() || srcType->isRealFloatingType()) {
1066 // This also includes converting booleans and enums to fixed point
1067 // types.
1068 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1069 }
1070
1071 llvm_unreachable("Unhandled scalar conversion to a fixed point type from "
1072 "another type.");
1073 }
1074
1075 srcType = srcType.getCanonicalType();
1076 dstType = dstType.getCanonicalType();
1077 if (srcType == dstType) {
1078 if (opts.emitImplicitIntegerSignChangeChecks)
1079 cgf.getCIRGenModule().errorNYI(loc,
1080 "implicit integer sign change checks");
1081 return src;
1082 }
1083
1084 if (dstType->isVoidType())
1085 return {};
1086
1087 mlir::Type mlirSrcType = src.getType();
1088
1089 // Handle conversions to bool first, they are special: comparisons against
1090 // 0.
1091 if (dstType->isBooleanType())
1092 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
1093
1094 mlir::Type mlirDstType = cgf.convertType(dstType);
1095
1096 if (srcType->isHalfType() &&
1097 !cgf.getContext().getLangOpts().NativeHalfType) {
1098 // Cast to FP using the intrinsic if the half type itself isn't supported.
1099 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1100 // Cast to other types through float, using FPExt, depending on whether
1101 // the half type itself is supported (as opposed to operations on half,
1102 // available with NativeHalfType).
1103 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1104 cgf.floatTy);
1105 srcType = cgf.getContext().FloatTy;
1106 mlirSrcType = cgf.floatTy;
1107 }
1108 }
1109
1110 // TODO(cir): LLVM codegen ignore conversions like int -> uint,
1111 // is there anything to be done for CIR here?
1112 if (mlirSrcType == mlirDstType) {
1113 if (opts.emitImplicitIntegerSignChangeChecks)
1114 cgf.getCIRGenModule().errorNYI(loc,
1115 "implicit integer sign change checks");
1116 return src;
1117 }
1118
1119 // Handle pointer conversions next: pointers can only be converted to/from
1120 // other pointers and integers. Check for pointer types in terms of LLVM, as
1121 // some native types (like Obj-C id) may map to a pointer type.
1122 if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1123 cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
1124 return builder.getNullPtr(dstPT, src.getLoc());
1125 }
1126
1127 if (isa<cir::PointerType>(mlirSrcType)) {
1128 // Must be an ptr to int cast.
1129 assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");
1130 return builder.createPtrToInt(src, mlirDstType);
1131 }
1132
1133 // A scalar can be splatted to an extended vector of the same element type
1134 if (dstType->isExtVectorType() && !srcType->isVectorType()) {
1135 // Sema should add casts to make sure that the source expression's type
1136 // is the same as the vector's element type (sans qualifiers)
1137 assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1138 srcType.getTypePtr() &&
1139 "Splatted expr doesn't match with vector element type?");
1140
1141 cgf.getCIRGenModule().errorNYI(loc, "vector splatting");
1142 return {};
1143 }
1144
1145 if (srcType->isMatrixType() && dstType->isMatrixType()) {
1146 cgf.getCIRGenModule().errorNYI(loc,
1147 "matrix type to matrix type conversion");
1148 return {};
1149 }
1150 assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
1151 "Internal error: conversion between matrix type and scalar type");
1152
1153 // Finally, we have the arithmetic types or vectors of arithmetic types.
1154 mlir::Value res = nullptr;
1155 mlir::Type resTy = mlirDstType;
1156
1157 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1158
1159 if (mlirDstType != resTy) {
1160 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1161 resTy);
1162 }
1163
1164 if (opts.emitImplicitIntegerTruncationChecks)
1165 cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");
1166
1167 if (opts.emitImplicitIntegerSignChangeChecks)
1168 cgf.getCIRGenModule().errorNYI(loc,
1169 "implicit integer sign change checks");
1170
1171 return res;
1172 }
1173
1174 BinOpInfo emitBinOps(const BinaryOperator *e,
1175 QualType promotionType = QualType()) {
1176 ignoreResultAssign = false;
1177 BinOpInfo result;
1178 result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
1179 result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
1180 if (!promotionType.isNull())
1181 result.fullType = promotionType;
1182 else
1183 result.fullType = e->getType();
1184 result.compType = result.fullType;
1185 if (const auto *vecType = result.fullType->getAs<VectorType>())
1186 result.compType = vecType->getElementType();
1187 result.opcode = e->getOpcode();
1188 result.loc = e->getSourceRange();
1189 result.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1190 result.e = e;
1191 return result;
1192 }
1193
1194 mlir::Value emitMul(const BinOpInfo &ops);
1195 mlir::Value emitDiv(const BinOpInfo &ops);
1196 mlir::Value emitRem(const BinOpInfo &ops);
1197 mlir::Value emitAdd(const BinOpInfo &ops);
1198 mlir::Value emitSub(const BinOpInfo &ops);
1199 mlir::Value emitShl(const BinOpInfo &ops);
1200 mlir::Value emitShr(const BinOpInfo &ops);
1201 mlir::Value emitAnd(const BinOpInfo &ops);
1202 mlir::Value emitXor(const BinOpInfo &ops);
1203 mlir::Value emitOr(const BinOpInfo &ops);
1204
1205 mlir::Value emitFixedPointBinOp(const BinOpInfo &ops);
1206
1207 LValue emitCompoundAssignLValue(
1208 const CompoundAssignOperator *e,
1209 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
1210 mlir::Value &result);
1211 mlir::Value
1212 emitCompoundAssign(const CompoundAssignOperator *e,
1213 mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
1214
1215 // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
1216 // codegen.
1217 QualType getPromotionType(QualType ty) {
1218 const clang::ASTContext &ctx = cgf.getContext();
1219 if (auto *complexTy = ty->getAs<ComplexType>()) {
1220 QualType elementTy = complexTy->getElementType();
1221 if (elementTy.UseExcessPrecision(ctx))
1222 return ctx.getComplexType(ctx.FloatTy);
1223 }
1224
1225 if (ty.UseExcessPrecision(cgf.getContext())) {
1226 if (auto *vt = ty->getAs<VectorType>()) {
1227 unsigned numElements = vt->getNumElements();
1228 return ctx.getVectorType(ctx.FloatTy, numElements, vt->getVectorKind());
1229 }
1230 return cgf.getContext().FloatTy;
1231 }
1232
1233 return QualType();
1234 }
1235
1236// Binary operators and binary compound assignment operators.
1237#define HANDLEBINOP(OP) \
1238 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1239 QualType promotionTy = getPromotionType(e->getType()); \
1240 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1241 if (result && !promotionTy.isNull()) \
1242 result = emitUnPromotedValue(result, e->getType()); \
1243 return result; \
1244 } \
1245 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1246 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1247 }
1248
1249 HANDLEBINOP(Mul)
1250 HANDLEBINOP(Div)
1251 HANDLEBINOP(Rem)
1252 HANDLEBINOP(Add)
1253 HANDLEBINOP(Sub)
1254 HANDLEBINOP(Shl)
1255 HANDLEBINOP(Shr)
1257 HANDLEBINOP(Xor)
1259#undef HANDLEBINOP
1260
1261 cir::CmpOpKind clangCmpToCIRCmp(clang::BinaryOperatorKind clangCmp) {
1262 switch (clangCmp) {
1263 case BO_LT:
1264 return cir::CmpOpKind::lt;
1265 case BO_GT:
1266 return cir::CmpOpKind::gt;
1267 case BO_LE:
1268 return cir::CmpOpKind::le;
1269 case BO_GE:
1270 return cir::CmpOpKind::ge;
1271 case BO_EQ:
1272 return cir::CmpOpKind::eq;
1273 case BO_NE:
1274 return cir::CmpOpKind::ne;
1275 default:
1276 llvm_unreachable("unsupported comparison kind for cir.cmp");
1277 }
1278 }
1279
1280 mlir::Value emitCmp(const BinaryOperator *e) {
1281 ignoreResultAssign = false;
1282 const mlir::Location loc = cgf.getLoc(e->getExprLoc());
1283 mlir::Value result;
1284 QualType lhsTy = e->getLHS()->getType();
1285 QualType rhsTy = e->getRHS()->getType();
1286
1287 cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
1288 if (lhsTy->getAs<MemberPointerType>()) {
1290 assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
1291 mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
1292 mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
1293 result = builder.createCompare(loc, kind, lhs, rhs);
1294 } else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
1295 BinOpInfo boInfo = emitBinOps(e);
1296 mlir::Value lhs = boInfo.lhs;
1297 mlir::Value rhs = boInfo.rhs;
1298
1299 if (lhsTy->isVectorType()) {
1300 if (!e->getType()->isVectorType()) {
1301 // If AltiVec, the comparison results in a numeric type, so we use
1302 // intrinsics comparing vectors and giving 0 or 1 as a result
1303 cgf.cgm.errorNYI(loc, "AltiVec comparison");
1304 } else {
1305 // Other kinds of vectors. Element-wise comparison returning
1306 // a vector.
1307 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1308 cgf.convertType(boInfo.fullType), kind,
1309 boInfo.lhs, boInfo.rhs);
1310 }
1311 } else if (boInfo.isFixedPointOp()) {
1312 result = emitFixedPointBinOp(boInfo);
1313 } else {
1314 // integers and pointers
1315 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1316 mlir::isa<cir::PointerType>(lhs.getType()) &&
1317 mlir::isa<cir::PointerType>(rhs.getType())) {
1318 cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");
1319 }
1320 result = builder.createCompare(loc, kind, lhs, rhs);
1321 }
1322 } else {
1323 assert((e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE) &&
1324 "Complex Comparison: can only be an equality comparison");
1325
1326 mlir::Value lhs;
1327 if (lhsTy->isAnyComplexType()) {
1328 lhs = cgf.emitComplexExpr(e->getLHS());
1329 } else {
1330 mlir::Value lhsReal = Visit(e->getLHS());
1331 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1332 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1333 }
1334
1335 mlir::Value rhs;
1336 if (rhsTy->isAnyComplexType()) {
1337 rhs = cgf.emitComplexExpr(e->getRHS());
1338 } else {
1339 mlir::Value rhsReal = Visit(e->getRHS());
1340 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1341 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1342 }
1343
1344 result = builder.createCompare(loc, kind, lhs, rhs);
1345 }
1346
1347 return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
1348 e->getExprLoc());
1349 }
1350
1351// Comparisons.
1352#define VISITCOMP(CODE) \
1353 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1354 VISITCOMP(LT)
1355 VISITCOMP(GT)
1356 VISITCOMP(LE)
1357 VISITCOMP(GE)
1358 VISITCOMP(EQ)
1359 VISITCOMP(NE)
1360#undef VISITCOMP
1361
1362 mlir::Value VisitBinAssign(const BinaryOperator *e) {
1363 const bool ignore = std::exchange(ignoreResultAssign, false);
1364
1365 mlir::Value rhs;
1366 LValue lhs;
1367
1368 switch (e->getLHS()->getType().getObjCLifetime()) {
1374 break;
1376 // __block variables need to have the rhs evaluated first, plus this
1377 // should improve codegen just a little.
1378 rhs = Visit(e->getRHS());
1380 // TODO(cir): This needs to be emitCheckedLValue() once we support
1381 // sanitizers
1382 lhs = cgf.emitLValue(e->getLHS());
1383
1384 // Store the value into the LHS. Bit-fields are handled specially because
1385 // the result is altered by the store, i.e., [C99 6.5.16p1]
1386 // 'An assignment expression has the value of the left operand after the
1387 // assignment...'.
1388 if (lhs.isBitField()) {
1390 rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);
1391 } else {
1392 cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
1394 cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);
1395 }
1396 }
1397
1398 // If the result is clearly ignored, return now.
1399 if (ignore)
1400 return nullptr;
1401
1402 // The result of an assignment in C is the assigned r-value.
1403 if (!cgf.getLangOpts().CPlusPlus)
1404 return rhs;
1405
1406 // If the lvalue is non-volatile, return the computed value of the
1407 // assignment.
1408 if (!lhs.isVolatile())
1409 return rhs;
1410
1411 // Otherwise, reload the value.
1412 return emitLoadOfLValue(lhs, e->getExprLoc());
1413 }
1414
1415 mlir::Value VisitBinComma(const BinaryOperator *e) {
1416 cgf.emitIgnoredExpr(e->getLHS());
1417 // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.
1418 return Visit(e->getRHS());
1419 }
1420
1421 mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {
1422 if (e->getType()->isVectorType()) {
1423 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1424 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1425 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1426
1427 mlir::Value lhs = Visit(e->getLHS());
1428 mlir::Value rhs = Visit(e->getRHS());
1429
1430 auto cmpOpKind = cir::CmpOpKind::ne;
1431 auto resultTy =
1432 mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
1433 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1434 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1435 return builder.createAnd(loc, lhs, rhs);
1436 }
1437
1439 mlir::Type resTy = cgf.convertType(e->getType());
1440 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1441
1442 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1443
1444 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1445
1446 auto resOp = cir::TernaryOp::create(
1447 builder, loc, lhsCondV, /*trueBuilder=*/
1448 [&](mlir::OpBuilder &b, mlir::Location loc) {
1449 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1450 b.getInsertionBlock()};
1451 cgf.curLexScope->setAsTernary();
1452 eval.beginEvaluation();
1453 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1454 eval.endEvaluation();
1455 lexScope.forceCleanup({&res});
1456 cir::YieldOp::create(b, loc, res);
1457 },
1458 /*falseBuilder*/
1459 [&](mlir::OpBuilder &b, mlir::Location loc) {
1460 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1461 b.getInsertionBlock()};
1462 cgf.curLexScope->setAsTernary();
1463 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1464 cir::YieldOp::create(b, loc, res.getRes());
1465 });
1466 return maybePromoteBoolResult(resOp.getResult(), resTy);
1467 }
1468
1469 mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {
1470 if (e->getType()->isVectorType()) {
1471 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1472 mlir::Type lhsTy = cgf.convertType(e->getLHS()->getType());
1473 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1474
1475 mlir::Value lhs = Visit(e->getLHS());
1476 mlir::Value rhs = Visit(e->getRHS());
1477
1478 auto cmpOpKind = cir::CmpOpKind::ne;
1479 auto resultTy =
1480 mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
1481 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1482 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1483 return builder.createOr(loc, lhs, rhs);
1484 }
1485
1487 mlir::Type resTy = cgf.convertType(e->getType());
1488 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1489
1490 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1491
1492 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1493
1494 auto resOp = cir::TernaryOp::create(
1495 builder, loc, lhsCondV, /*trueBuilder=*/
1496 [&](mlir::OpBuilder &b, mlir::Location loc) {
1497 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1498 b.getInsertionBlock()};
1499 cgf.curLexScope->setAsTernary();
1500 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1501 cir::YieldOp::create(b, loc, res.getRes());
1502 },
1503 /*falseBuilder*/
1504 [&](mlir::OpBuilder &b, mlir::Location loc) {
1505 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1506 b.getInsertionBlock()};
1507 cgf.curLexScope->setAsTernary();
1508 eval.beginEvaluation();
1509 mlir::Value res = cgf.evaluateExprAsBool(e->getRHS());
1510 eval.endEvaluation();
1511 lexScope.forceCleanup({&res});
1512 cir::YieldOp::create(b, loc, res);
1513 });
1514
1515 return maybePromoteBoolResult(resOp.getResult(), resTy);
1516 }
1517
1518 mlir::Value VisitBinPtrMemD(const BinaryOperator *e) {
1519 return emitLoadOfLValue(e);
1520 }
1521
1522 mlir::Value VisitBinPtrMemI(const BinaryOperator *e) {
1523 return emitLoadOfLValue(e);
1524 }
1525
1526 // Other Operators.
1527 mlir::Value VisitBlockExpr(const BlockExpr *e) {
1528 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: block");
1529 return {};
1530 }
1531
1532 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1533 return Visit(e->getChosenSubExpr());
1534 }
1535
1536 mlir::Value VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1537 cgf.cgm.errorNYI(e->getSourceRange(),
1538 "ScalarExprEmitter: objc string literal");
1539 return {};
1540 }
1541 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1542 cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: objc boxed");
1543 return {};
1544 }
1545 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1546 cgf.cgm.errorNYI(e->getSourceRange(),
1547 "ScalarExprEmitter: objc array literal");
1548 return {};
1549 }
1550 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1551 cgf.cgm.errorNYI(e->getSourceRange(),
1552 "ScalarExprEmitter: objc dictionary literal");
1553 return {};
1554 }
1555
1556 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1557 mlir::Value src, unsigned numElementsDst) {
1558 static constexpr int64_t mask[] = {0, 1, 2, -1};
1559 return builder.createVecShuffle(
1560 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1561 }
1562
1563 // Create cast instructions for converting MLIR value \p Src to MLIR type \p
1564 // DstTy. \p Src has the same size as \p DstTy. Both are single value types
1565 // but could be scalar or vectors of different lengths, and either can be
1566 // pointer.
1567 //
1568 // There are 4 cases:
1569 // 1. non-pointer -> non-pointer : needs 1 bitcast
1570 // 2. pointer -> pointer : needs 1 bitcast or addrspacecast
1571 // 3. pointer -> non-pointer
1572 // a) pointer -> intptr_t : needs 1 ptrtoint
1573 // b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast
1574 // 4. non-pointer -> pointer
1575 // a) intptr_t -> pointer : needs 1 inttoptr
1576 // b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr
1577 //
1578 // Note: for cases 3b and 4b two casts are required since LLVM casts do not
1579 // allow casting directly between pointer types and non-integer non-pointer
1580 // types.
1581 mlir::Value createCastsForTypeOfSameSize(mlir::Value src, mlir::Type dstTy) {
1582 mlir::Type srcTy = src.getType();
1583
1584 // Case 1.
1585 if (!isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy))
1586 return builder.createBitcast(src, dstTy);
1587
1588 // Case 2.
1589 if (isa<cir::PointerType>(srcTy) && isa<cir::PointerType>(dstTy)) {
1590 cgf.cgm.errorNYI(
1591 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1592 return {};
1593 }
1594
1595 // Case 3.
1596 if (isa<cir::PointerType>(srcTy) && !isa<cir::PointerType>(dstTy)) {
1597 if (!isa<cir::IntType>(dstTy)) {
1598 cgf.cgm.errorNYI(
1599 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1600 }
1601
1602 cgf.cgm.errorNYI(
1603 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1604 return {};
1605 }
1606
1607 // Case 4b.
1608 if (!isa<cir::IntType>(srcTy)) {
1609 cgf.cgm.errorNYI(
1610 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1611 return {};
1612 }
1613 // Cases 4a and 4b.
1614 return builder.createIntToPtr(src, dstTy);
1615 }
1616
1617 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1618 mlir::Value src = cgf.emitScalarExpr(e->getSrcExpr());
1619 mlir::Type srcTy = src.getType();
1620 mlir::Type dstTy = cgf.convertType(e->getType());
1621
1622 unsigned numElementsSrc = isa<cir::VectorType>(srcTy)
1623 ? cast<cir::VectorType>(srcTy).getSize()
1624 : 0;
1625 unsigned numElementsDst = isa<cir::VectorType>(dstTy)
1626 ? cast<cir::VectorType>(dstTy).getSize()
1627 : 0;
1628
1629 // Use bit vector expansion for ext_vector_type boolean vectors.
1630 if (e->getType()->isExtVectorBoolType()) {
1631 cgf.cgm.errorNYI(e->getSourceRange(),
1632 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1633 return {};
1634 }
1635
1636 // Going from vec3 to non-vec3 is a special case and requires a shuffle
1637 // vector to get a vec4, then a bitcast if the target type is different.
1638 if (numElementsSrc == 3 && numElementsDst != 3) {
1639 cgf.cgm.errorNYI(e->getSourceRange(),
1640 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1641 "numElemsDst != 3");
1642 return {};
1643 }
1644
1645 // Going from non-vec3 to vec3 is a special case and requires a bitcast
1646 // to vec4 if the original type is not vec4, then a shuffle vector to
1647 // get a vec3.
1648 if (numElementsSrc != 3 && numElementsDst == 3) {
1649 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1650 auto dstElemTy = cast<cir::VectorType>(dstTy).getElementType();
1651 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1652 src = createCastsForTypeOfSameSize(src, dstVec4Ty);
1653 src = convertVec3AndVec4(builder, loc, src, 3);
1654 return src;
1655 }
1656
1657 return createCastsForTypeOfSameSize(src, dstTy);
1658 }
1659
1660 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1661 return cgf.emitAtomicExpr(e).getValue();
1662 }
1663};
1664
1665LValue ScalarExprEmitter::emitCompoundAssignLValue(
1666 const CompoundAssignOperator *e,
1667 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
1668 mlir::Value &result) {
1670 return cgf.emitScalarCompoundAssignWithComplex(e, result);
1671
1672 QualType lhsTy = e->getLHS()->getType();
1673 BinOpInfo opInfo;
1674
1675 // Emit the RHS first. __block variables need to have the rhs evaluated
1676 // first, plus this should improve codegen a little.
1677
1678 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
1679 if (promotionTypeCR.isNull())
1680 promotionTypeCR = e->getComputationResultType();
1681
1682 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
1683 QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
1684
1685 if (!promotionTypeRHS.isNull())
1686 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
1687 else
1688 opInfo.rhs = Visit(e->getRHS());
1689
1690 opInfo.fullType = promotionTypeCR;
1691 opInfo.compType = opInfo.fullType;
1692 if (const auto *vecType = opInfo.fullType->getAs<VectorType>())
1693 opInfo.compType = vecType->getElementType();
1694 opInfo.opcode = e->getOpcode();
1695 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1696 opInfo.e = e;
1697 opInfo.loc = e->getSourceRange();
1698
1699 // Load/convert the LHS
1700 LValue lhsLV = cgf.emitLValue(e->getLHS());
1701
1702 if (lhsTy->getAs<AtomicType>()) {
1703 cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
1704 return LValue();
1705 }
1706
1707 opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
1708
1709 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->getSourceRange()};
1710 SourceLocation loc = e->getExprLoc();
1711 if (!promotionTypeLHS.isNull())
1712 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1713 else
1714 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1715 e->getComputationLHSType(), loc);
1716
1717 // Expand the binary operator.
1718 result = (this->*func)(opInfo);
1719
1720 // Convert the result back to the LHS type,
1721 // potentially with Implicit Conversion sanitizer check.
1722 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1723 ScalarConversionOpts(cgf.sanOpts));
1724
1725 // Store the result value into the LHS lvalue. Bit-fields are handled
1726 // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
1727 // 'An assignment expression has the value of the left operand after the
1728 // assignment...'.
1729 if (lhsLV.isBitField())
1730 cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);
1731 else
1732 cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
1733
1734 if (cgf.getLangOpts().OpenMP)
1735 cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
1736
1737 return lhsLV;
1738}
1739
1740mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1741 mlir::Value value,
1742 CastKind kind,
1743 QualType destTy) {
1744 cir::CastKind castOpKind;
1745 switch (kind) {
1746 case CK_FloatingComplexToReal:
1747 castOpKind = cir::CastKind::float_complex_to_real;
1748 break;
1749 case CK_IntegralComplexToReal:
1750 castOpKind = cir::CastKind::int_complex_to_real;
1751 break;
1752 case CK_FloatingComplexToBoolean:
1753 castOpKind = cir::CastKind::float_complex_to_bool;
1754 break;
1755 case CK_IntegralComplexToBoolean:
1756 castOpKind = cir::CastKind::int_complex_to_bool;
1757 break;
1758 default:
1759 llvm_unreachable("invalid complex-to-scalar cast kind");
1760 }
1761
1762 return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));
1763}
1764
1765mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
1766 QualType promotionType) {
1767 e = e->IgnoreParens();
1768 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
1769 switch (bo->getOpcode()) {
1770#define HANDLE_BINOP(OP) \
1771 case BO_##OP: \
1772 return emit##OP(emitBinOps(bo, promotionType));
1773 HANDLE_BINOP(Add)
1774 HANDLE_BINOP(Sub)
1775 HANDLE_BINOP(Mul)
1776 HANDLE_BINOP(Div)
1777#undef HANDLE_BINOP
1778 default:
1779 break;
1780 }
1781 } else if (const auto *uo = dyn_cast<UnaryOperator>(e)) {
1782 switch (uo->getOpcode()) {
1783 case UO_Imag:
1784 case UO_Real:
1785 return VisitRealImag(uo, promotionType);
1786 case UO_Minus:
1787 return VisitUnaryMinus(uo, promotionType);
1788 case UO_Plus:
1789 return VisitUnaryPlus(uo, promotionType);
1790 default:
1791 break;
1792 }
1793 }
1794 mlir::Value result = Visit(const_cast<Expr *>(e));
1795 if (result) {
1796 if (!promotionType.isNull())
1797 return emitPromotedValue(result, promotionType);
1798 return emitUnPromotedValue(result, e->getType());
1799 }
1800 return result;
1801}
1802
1803mlir::Value ScalarExprEmitter::emitCompoundAssign(
1804 const CompoundAssignOperator *e,
1805 mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
1806
1807 bool ignore = std::exchange(ignoreResultAssign, false);
1808 mlir::Value rhs;
1809 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1810
1811 // If the result is clearly ignored, return now.
1812 if (ignore)
1813 return {};
1814
1815 // The result of an assignment in C is the assigned r-value.
1816 if (!cgf.getLangOpts().CPlusPlus)
1817 return rhs;
1818
1819 // If the lvalue is non-volatile, return the computed value of the assignment.
1820 if (!lhs.isVolatile())
1821 return rhs;
1822
1823 // Otherwise, reload the value.
1824 return emitLoadOfLValue(lhs, e->getExprLoc());
1825}
1826
1827mlir::Value
1828ScalarExprEmitter::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
1829 ASTContext &context = cgf.getContext();
1830 mlir::Location loc = cgf.getLoc(e->getSourceRange());
1831 cir::GlobalOp globalConstStr =
1832 cgf.cgm.createGlobalString(loc, e->ComputeName(context), "__usn_str");
1833
1834 // Unlike LLVM IR, CIR pointers are typed, so the bitcast and the address
1835 // space cast are emitted as separate operations when both are needed.
1836 mlir::Value addr = builder.createGetGlobal(loc, globalConstStr);
1837 auto exprTy = mlir::cast<cir::PointerType>(convertType(e->getType()));
1838 auto addrTy = mlir::cast<cir::PointerType>(addr.getType());
1839 if (addrTy.getAddrSpace() != exprTy.getAddrSpace())
1840 addr = cgf.performAddrSpaceCast(
1841 addr, builder.getPointerTo(addrTy.getPointee(), exprTy.getAddrSpace()));
1842 return builder.createBitcast(loc, addr, exprTy);
1843}
1844
1845mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1846 CIRGenFunction::FullExprCleanupScope scope(cgf, e->getSubExpr());
1847 mlir::Value v = Visit(e->getSubExpr());
1848 // Defend against dominance problems caused by jumps out of expression
1849 // evaluation through the shared cleanup block.
1850 scope.exit({&v});
1851 return v;
1852}
1853
1854} // namespace
1855
1856LValue
1858 ScalarExprEmitter emitter(*this, builder);
1859 mlir::Value result;
1860 switch (e->getOpcode()) {
1861#define COMPOUND_OP(Op) \
1862 case BO_##Op##Assign: \
1863 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1864 result)
1865 COMPOUND_OP(Mul);
1866 COMPOUND_OP(Div);
1867 COMPOUND_OP(Rem);
1868 COMPOUND_OP(Add);
1869 COMPOUND_OP(Sub);
1870 COMPOUND_OP(Shl);
1871 COMPOUND_OP(Shr);
1873 COMPOUND_OP(Xor);
1874 COMPOUND_OP(Or);
1875#undef COMPOUND_OP
1876
1877 case BO_PtrMemD:
1878 case BO_PtrMemI:
1879 case BO_Mul:
1880 case BO_Div:
1881 case BO_Rem:
1882 case BO_Add:
1883 case BO_Sub:
1884 case BO_Shl:
1885 case BO_Shr:
1886 case BO_LT:
1887 case BO_GT:
1888 case BO_LE:
1889 case BO_GE:
1890 case BO_EQ:
1891 case BO_NE:
1892 case BO_Cmp:
1893 case BO_And:
1894 case BO_Xor:
1895 case BO_Or:
1896 case BO_LAnd:
1897 case BO_LOr:
1898 case BO_Assign:
1899 case BO_Comma:
1900 llvm_unreachable("Not valid compound assignment operators");
1901 }
1902 llvm_unreachable("Unhandled compound assignment operator");
1903}
1904
1905/// Emit the computation of the specified expression of scalar type.
1907 bool ignoreResultAssign) {
1908 assert(e && hasScalarEvaluationKind(e->getType()) &&
1909 "Invalid scalar expression to emit");
1910
1911 return ScalarExprEmitter(*this, builder, ignoreResultAssign)
1912 .Visit(const_cast<Expr *>(e));
1913}
1914
1916 QualType promotionType) {
1917 if (!promotionType.isNull())
1918 return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);
1919 return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1920}
1921
1922[[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {
1923 // If a null pointer expression's type is the C++0x nullptr_t and
1924 // the expression is not a simple literal, it must be evaluated
1925 // for its potential side effects.
1927 return false;
1928 return e->getType()->isNullPtrType();
1929}
1930
1931/// If \p e is a widened promoted integer, get its base (unpromoted) type.
1932static std::optional<QualType>
1933getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {
1934 const Expr *base = e->IgnoreImpCasts();
1935 if (e == base)
1936 return std::nullopt;
1937
1938 QualType baseTy = base->getType();
1939 if (!astContext.isPromotableIntegerType(baseTy) ||
1940 astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))
1941 return std::nullopt;
1942
1943 return baseTy;
1944}
1945
1946/// Check if \p e is a widened promoted integer.
1947[[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,
1948 const Expr *e) {
1949 return getUnwidenedIntegerType(astContext, e).has_value();
1950}
1951
1952/// Check if we can skip the overflow check for \p Op.
1953[[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,
1954 const BinOpInfo &op) {
1955 assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1956 "Expected a unary or binary operator");
1957
1958 // If the binop has constant inputs and we can prove there is no overflow,
1959 // we can elide the overflow check.
1960 if (!op.mayHaveIntegerOverflow())
1961 return true;
1962
1963 // If a unary op has a widened operand, the op cannot overflow.
1964 if (const auto *uo = dyn_cast<UnaryOperator>(op.e))
1965 return !uo->canOverflow();
1966
1967 // We usually don't need overflow checks for binops with widened operands.
1968 // Multiplication with promoted unsigned operands is a special case.
1969 const auto *bo = cast<BinaryOperator>(op.e);
1970 std::optional<QualType> optionalLHSTy =
1971 getUnwidenedIntegerType(astContext, bo->getLHS());
1972 if (!optionalLHSTy)
1973 return false;
1974
1975 std::optional<QualType> optionalRHSTy =
1976 getUnwidenedIntegerType(astContext, bo->getRHS());
1977 if (!optionalRHSTy)
1978 return false;
1979
1980 QualType lhsTy = *optionalLHSTy;
1981 QualType rhsTy = *optionalRHSTy;
1982
1983 // This is the simple case: binops without unsigned multiplication, and with
1984 // widened operands. No overflow check is needed here.
1985 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1986 !lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())
1987 return true;
1988
1989 // For unsigned multiplication the overflow check can be elided if either one
1990 // of the unpromoted types are less than half the size of the promoted type.
1991 unsigned promotedSize = astContext.getTypeSize(op.e->getType());
1992 return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||
1993 (2 * astContext.getTypeSize(rhsTy)) < promotedSize;
1994}
1995
1996/// Emit pointer + index arithmetic.
1998 const BinOpInfo &op,
1999 bool isSubtraction) {
2000 // Must have binary (not unary) expr here. Unary pointer
2001 // increment/decrement doesn't use this path.
2003
2004 mlir::Value pointer = op.lhs;
2005 Expr *pointerOperand = expr->getLHS();
2006 mlir::Value index = op.rhs;
2007 Expr *indexOperand = expr->getRHS();
2008
2009 // In the case of subtraction, the FE has ensured that the LHS is always the
2010 // pointer. However, addition can have the pointer on either side. We will
2011 // always have a pointer operand and an integer operand, so if the LHS wasn't
2012 // a pointer, we need to swap our values.
2013 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
2014 std::swap(pointer, index);
2015 std::swap(pointerOperand, indexOperand);
2016 }
2017 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
2018 "Need a pointer operand");
2019 assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");
2020
2021 // Some versions of glibc and gcc use idioms (particularly in their malloc
2022 // routines) that add a pointer-sized integer (known to be a pointer value)
2023 // to a null pointer in order to cast the value back to an integer or as
2024 // part of a pointer alignment algorithm. This is undefined behavior, but
2025 // we'd like to be able to compile programs that use it.
2026 //
2027 // Normally, we'd generate a GEP with a null-pointer base here in response
2028 // to that code, but it's also UB to dereference a pointer created that
2029 // way. Instead (as an acknowledged hack to tolerate the idiom) we will
2030 // generate a direct cast of the integer value to a pointer.
2031 //
2032 // The idiom (p = nullptr + N) is not met if any of the following are true:
2033 //
2034 // The operation is subtraction.
2035 // The index is not pointer-sized.
2036 // The pointer type is not byte-sized.
2037 //
2039 cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))
2040 return cgf.getBuilder().createIntToPtr(index, pointer.getType());
2041
2042 // Differently from LLVM codegen, ABI bits for index sizes is handled during
2043 // LLVM lowering.
2044
2045 // If this is subtraction, negate the index.
2046 if (isSubtraction)
2047 index = cgf.getBuilder().createNeg(cgf.getLoc(op.e->getExprLoc()), index);
2048
2050
2051 const PointerType *pointerType =
2052 pointerOperand->getType()->getAs<PointerType>();
2053 if (!pointerType) {
2054 cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");
2055 return nullptr;
2056 }
2057
2058 QualType elementType = pointerType->getPointeeType();
2059 if (const VariableArrayType *vla =
2060 cgf.getContext().getAsVariableArrayType(elementType)) {
2061 mlir::Value numElements = cgf.getVLASize(vla).numElts;
2062 mlir::Location loc = cgf.getLoc(op.e->getExprLoc());
2063 index = cgf.getBuilder().createCast(cir::CastKind::integral, index,
2064 numElements.getType());
2065 // GEP indexes are signed, and scaling an index isn't permitted to
2066 // signed-overflow, so we use the same semantics for our explicit
2067 // multiply. We suppress this if overflow is not undefined behavior.
2068 cir::OverflowBehavior overflowBehavior =
2069 cgf.getLangOpts().PointerOverflowDefined
2072 index =
2073 cgf.getBuilder().createMul(loc, index, numElements, overflowBehavior);
2075 return cir::PtrStrideOp::create(cgf.getBuilder(), loc, pointer.getType(),
2076 pointer, index);
2077 }
2078
2080 return cir::PtrStrideOp::create(cgf.getBuilder(),
2081 cgf.getLoc(op.e->getExprLoc()),
2082 pointer.getType(), pointer, index);
2083}
2084
2085static bool isIntegerVectorBinOp(mlir::Type ty) {
2086 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
2087 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
2088}
2089
2090// Construct a cir.fmuladd op to represent a fused mul-add of `mulOp` and
2091// `addend`. Use negMul and negAdd to negate the first operand of the mul or
2092// the addend respectively. This allows fmuladd to represent a*b-c, or c-a*b.
2093// Patterns in LLVM should catch the negated forms and translate them to
2094// efficient operations.
2095static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp,
2096 mlir::Value addend, CIRGenBuilderTy &builder,
2097 bool negMul, bool negAdd) {
2098 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
2099 mlir::Value mulOp0 = mulOp.getLhs();
2100 mlir::Value mulOp1 = mulOp.getRhs();
2101 if (negMul)
2102 mulOp0 = builder.createFNeg(loc, mulOp0);
2103 if (negAdd)
2104 addend = builder.createFNeg(loc, addend);
2105
2106 // Carry the mul's fenv attribute so a constrained fmul yields a constrained
2107 // fmuladd; the builder is under the add's FP options, not the mul's.
2108 mlir::Value fmuladd =
2109 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
2110 addend, mulOp.getFenvAttr());
2111 mulOp.erase();
2112 return fmuladd;
2113}
2114
2115// Check whether it would be legal to emit a cir.fmuladd op to represent op
2116// and if so, build it.
2117//
2118// Checks that (a) the operation is fusable, and (b) -ffp-contract=on.
2119// Does NOT check the type of the operation - it's assumed that this function
2120// will be called from contexts where it's known that the type is contractable.
2121static mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op,
2122 CIRGenBuilderTy &builder,
2123 bool isSub = false) {
2124 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2125 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2126 "Only fadd/fsub can be the root of an fmuladd.");
2127
2128 // Check whether this op is fusable, i.e. -ffp-contract=on. -ffp-contract=fast
2129 // is represented by the `contract` flag on the fmul/fadd instead.
2130 if (!op.fpFeatures.allowFPContractWithinStatement())
2131 return nullptr;
2132
2133 mlir::Value lhs = op.lhs;
2134 mlir::Value rhs = op.rhs;
2135
2136 // Peek through fneg to look for fmul. Make sure the fneg has no other users,
2137 // and that it is the only use of its operand.
2138 bool negLHS = false;
2139 if (auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2140 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2141 lhs = lhsNeg.getInput();
2142 negLHS = true;
2143 }
2144 }
2145
2146 bool negRHS = false;
2147 if (auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2148 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2149 rhs = rhsNeg.getInput();
2150 negRHS = true;
2151 }
2152 }
2153
2154 // We have a potentially fusable op. Look for a mul on one of the operands.
2155 // Also make sure that the mul result isn't used directly. In that case,
2156 // there's no point creating a muladd operation.
2157 if (auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2158 if (lhsMul.getResult().use_empty() || negLHS) {
2159 // If we looked through fneg, erase it.
2160 if (negLHS)
2161 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2162 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2163 }
2164 }
2165 if (auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2166 if (rhsMul.getResult().use_empty() || negRHS) {
2167 // If we looked through fneg, erase it.
2168 if (negRHS)
2169 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2170 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS, false);
2171 }
2172 }
2173
2174 return nullptr;
2175}
2176
2177mlir::Value ScalarExprEmitter::emitFixedPointIncDec(const UnaryOperator *e,
2178 mlir::Value value,
2179 QualType type) {
2180 // Fixed-point types are tricky. In some cases, it isn't possible to
2181 // represent a 1 or a -1 in the type at all. Piggyback off of
2182 // EmitFixedPointBinOp to avoid having to reimplement saturation.
2183 BinOpInfo info;
2184 info.loc = e->getSourceRange();
2185 info.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
2186 info.e = e;
2187 info.compType = info.fullType = e->getType();
2188 info.opcode = e->isIncrementOp() ? BO_Add : BO_Sub;
2189 info.lhs = value;
2190 info.rhs = builder.getConstInt(cgf.getLoc(info.loc), value.getType(), 1);
2191 // If the type is signed, it's better to represent this as +(-1) or -(-1),
2192 // since -1 is guaranteed to be representable.
2193 // FIXME(cir): This is a carry-over from Classic codegen, we should probably
2194 // figure out if ++ -> -(-1) and -- -> +(-1) is REALLY what we want? For now
2195 // we are just doing what classic does here.
2196 if (type->isSignedFixedPointType()) {
2197 info.opcode = e->isIncrementOp() ? BO_Sub : BO_Add;
2198 info.rhs = builder.createNeg(cgf.getLoc(info.loc), info.rhs);
2199 }
2200 // Now, convert from our invented integer literal to the type of the unary
2201 // op. This will upscale and saturate if necessary. This value can become
2202 // undef in some cases.
2203 CIRGenFixedPointBuilder fpbuilder(builder, cgf.getLoc(info.loc));
2204 auto dstSema = cgf.getContext().getFixedPointSemantics(info.fullType);
2205 info.rhs =
2206 fpbuilder.createIntegerToFixed(info.rhs, /*srcIsSigned=*/true, dstSema);
2207 return emitFixedPointBinOp(info);
2208}
2209
2210mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2211 QualType srcTy,
2212 QualType dstTy,
2213 mlir::Location loc) {
2214 assert(srcTy->isFixedPointType() || dstTy->isFixedPointType());
2215
2216 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2217 mlir::Value result;
2218 if (srcTy->isRealFloatingType()) {
2219 assert(dstTy->isFixedPointType());
2220 result = fpBuilder.createFloatingToFixed(
2221 src, cgf.getContext().getFixedPointSemantics(dstTy));
2222 } else if (dstTy->isRealFloatingType()) {
2223 assert(srcTy->isFixedPointType());
2224 result = fpBuilder.createFixedToFloating(
2225 src, cgf.getContext().getFixedPointSemantics(srcTy),
2226 cgf.convertType(dstTy));
2227 } else {
2228 llvm::FixedPointSemantics srcFPSema =
2230 llvm::FixedPointSemantics dstFPSema =
2232
2233 if (dstTy->isIntegerType())
2234 result = fpBuilder.createFixedToInteger(
2235 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2236 else if (srcTy->isIntegerType())
2237 result =
2238 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2239 else {
2240 assert(srcTy->isFixedPointType() && dstTy->isFixedPointType());
2241 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2242 }
2243 }
2244 return result;
2245}
2246
2247mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {
2248 const mlir::Location loc = cgf.getLoc(ops.loc);
2249 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2250 ops.compType->isSignedIntegerOrEnumerationType()) {
2251 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2252 case LangOptions::SOB_Defined:
2253 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2254 return builder.createMul(loc, ops.lhs, ops.rhs);
2255 [[fallthrough]];
2256 case LangOptions::SOB_Undefined:
2257 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2258 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
2259 [[fallthrough]];
2260 case LangOptions::SOB_Trapping:
2261 if (canElideOverflowCheck(cgf.getContext(), ops))
2262 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
2263 cgf.cgm.errorNYI("sanitizers");
2264 }
2265 }
2266
2267 if (ops.fullType->isConstantMatrixType()) {
2268 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2269
2270 if (isa<cir::MatrixType>(ops.lhs.getType()) &&
2271 isa<cir::MatrixType>(ops.rhs.getType()))
2272 return builder.createMatrixMultiply(loc, ops.lhs, ops.rhs);
2273
2274 auto [lhs, rhs] =
2275 builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
2276 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2277 return builder.createFMul(loc, lhs, rhs);
2278 return builder.createMul(loc, lhs, rhs);
2279 }
2280
2281 if (ops.compType->isUnsignedIntegerType() &&
2282 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2283 !canElideOverflowCheck(cgf.getContext(), ops))
2284 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2285
2286 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2287 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2288 return builder.createFMul(loc, ops.lhs, ops.rhs);
2289 }
2290
2291 if (ops.isFixedPointOp())
2292 return emitFixedPointBinOp(ops);
2293
2294 return cir::MulOp::create(builder, cgf.getLoc(ops.loc),
2295 cgf.convertType(ops.fullType), ops.lhs, ops.rhs);
2296}
2297mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
2298 const mlir::Location loc = cgf.getLoc(ops.loc);
2299 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2300 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2301 return builder.createFDiv(loc, ops.lhs, ops.rhs);
2302 }
2303
2304 if (ops.fullType->isConstantMatrixType()) {
2305 assert(mlir::isa<cir::MatrixType>(ops.lhs.getType()) &&
2306 "first operand must be a matrix");
2307 assert(cir::isAnyIntegerOrFloatingPointType(ops.rhs.getType()) &&
2308 "second operand must be an arithmetic type");
2309
2310 auto [lhs, rhs] =
2311 builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
2312
2313 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2314 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2315 return builder.createFDiv(loc, lhs, rhs);
2316 return builder.createDiv(loc, lhs, rhs);
2317 }
2318
2319 if (ops.isFixedPointOp())
2320 return emitFixedPointBinOp(ops);
2321
2322 return cir::DivOp::create(builder, loc, cgf.convertType(ops.fullType),
2323 ops.lhs, ops.rhs);
2324}
2325mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
2326 const mlir::Location loc = cgf.getLoc(ops.loc);
2327 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2328 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2329 return builder.createFRem(loc, ops.lhs, ops.rhs);
2330 }
2331 return cir::RemOp::create(builder, loc, cgf.convertType(ops.fullType),
2332 ops.lhs, ops.rhs);
2333}
2334
2335mlir::Value ScalarExprEmitter::emitFixedPointBinOp(const BinOpInfo &ops) {
2336 // This is either a binary operation where at least one of the operands is
2337 // a fixed-point type, or a unary operation where the operand is a fixed-point
2338 // type. The result type of a binary operation is determined by
2339 // Sema::handleFixedPointConversions().
2340 QualType resultTy = ops.compType;
2341 QualType lhsTy, rhsTy;
2342 if (const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2343 rhsTy = binOp->getRHS()->getType();
2344 if (const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2345 // For compound assignment, the effective type of the LHS at this point
2346 // is the computation LHS type, not the actual LHS type, and the final
2347 // result type is not the type of the expression but rather the
2348 // computation result type.
2349 lhsTy = cao->getComputationLHSType();
2350 resultTy = cao->getComputationResultType();
2351 } else {
2352 lhsTy = binOp->getLHS()->getType();
2353 }
2354 } else if (const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2355 lhsTy = unOp->getSubExpr()->getType();
2356 rhsTy = unOp->getSubExpr()->getType();
2357 }
2358 ASTContext &ctx = cgf.getContext();
2359 mlir::Value lhs = ops.lhs;
2360 mlir::Value rhs = ops.rhs;
2361
2362 auto lhsFixedSema = ctx.getFixedPointSemantics(lhsTy);
2363 auto rhsFixedSema = ctx.getFixedPointSemantics(rhsTy);
2364 auto resultFixedSema = ctx.getFixedPointSemantics(resultTy);
2365 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2366
2367 // Perform the actual operation.
2368 mlir::Value result;
2369 CIRGenFixedPointBuilder fpbuilder(builder, cgf.getLoc(ops.loc));
2370 switch (ops.opcode) {
2371 case BO_AddAssign:
2372 case BO_Add:
2373 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2374 break;
2375 case BO_SubAssign:
2376 case BO_Sub:
2377 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2378 break;
2379 case BO_MulAssign:
2380 case BO_Mul:
2381 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2382 break;
2383 case BO_DivAssign:
2384 case BO_Div:
2385 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2386 break;
2387 case BO_ShlAssign:
2388 case BO_Shl:
2389 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2390 break;
2391 case BO_ShrAssign:
2392 case BO_Shr:
2393 result = fpbuilder.createShr(lhs, rhs);
2394 break;
2395 case BO_LT:
2396 case BO_GT:
2397 case BO_LE:
2398 case BO_GE:
2399 case BO_EQ:
2400 case BO_NE:
2401 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2402 clangCmpToCIRCmp(ops.opcode));
2403 case BO_Cmp:
2404 case BO_LAnd:
2405 case BO_LOr:
2406 llvm_unreachable("Found unimplemented fixed point binary operation");
2407 case BO_PtrMemD:
2408 case BO_PtrMemI:
2409 case BO_Rem:
2410 case BO_Xor:
2411 case BO_And:
2412 case BO_Or:
2413 case BO_Assign:
2414 case BO_RemAssign:
2415 case BO_AndAssign:
2416 case BO_XorAssign:
2417 case BO_OrAssign:
2418 case BO_Comma:
2419 llvm_unreachable(
2420 "Found unsupported binary operation for fixed point types.");
2421 }
2422
2423 bool isShift = BinaryOperator::isShiftOp(ops.opcode) ||
2425 // Convert to the result type.
2426 return fpbuilder.createFixedToFixed(
2427 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2428}
2429
2430mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
2431 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2432 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2433 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/
2434 false);
2435
2436 const mlir::Location loc = cgf.getLoc(ops.loc);
2437 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2438 ops.compType->isSignedIntegerOrEnumerationType()) {
2439 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2440 case LangOptions::SOB_Defined:
2441 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2442 return builder.createAdd(loc, ops.lhs, ops.rhs);
2443 [[fallthrough]];
2444 case LangOptions::SOB_Undefined:
2445 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2446 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2447 [[fallthrough]];
2448 case LangOptions::SOB_Trapping:
2449 if (canElideOverflowCheck(cgf.getContext(), ops))
2450 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
2451 cgf.cgm.errorNYI("sanitizers");
2452 }
2453 }
2454 if (ops.fullType->isConstantMatrixType()) {
2455 // Like llvm::MatrixBuilder::CreateAdd, splat a scalar operand to the matrix
2456 // type before adding.
2457 auto [lhs, rhs] =
2458 builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
2459
2460 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2461 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2462 return builder.createFAdd(loc, lhs, rhs);
2463 return builder.createAdd(loc, lhs, rhs);
2464 }
2465
2466 if (ops.compType->isUnsignedIntegerType() &&
2467 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2468 !canElideOverflowCheck(cgf.getContext(), ops))
2469 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2470
2471 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2472 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2473 // Try to form an fmuladd.
2474 if (mlir::Value fmuladd = tryEmitFMulAdd(loc, ops, builder))
2475 return fmuladd;
2476 return builder.createFAdd(loc, ops.lhs, ops.rhs);
2477 }
2478
2479 if (ops.isFixedPointOp())
2480 return emitFixedPointBinOp(ops);
2481
2482 return builder.createAdd(loc, ops.lhs, ops.rhs);
2483}
2484
2485mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
2486 const mlir::Location loc = cgf.getLoc(ops.loc);
2487 // The LHS is always a pointer if either side is.
2488 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2489 if (!isIntegerVectorBinOp(ops.lhs.getType()) &&
2490 ops.compType->isSignedIntegerOrEnumerationType()) {
2491 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
2492 case LangOptions::SOB_Defined: {
2493 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2494 return builder.createSub(loc, ops.lhs, ops.rhs);
2495 [[fallthrough]];
2496 }
2497 case LangOptions::SOB_Undefined:
2498 if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
2499 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2500 [[fallthrough]];
2501 case LangOptions::SOB_Trapping:
2502 if (canElideOverflowCheck(cgf.getContext(), ops))
2503 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
2504 cgf.cgm.errorNYI("sanitizers");
2505 }
2506 }
2507
2508 if (ops.fullType->isConstantMatrixType()) {
2509 // Like llvm::MatrixBuilder::CreateSub, splat a scalar operand to the
2510 // matrix type before adding.
2511 auto [lhs, rhs] =
2512 builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
2513
2514 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2515 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2516 return builder.createFSub(loc, lhs, rhs);
2517 return builder.createSub(loc, lhs, rhs);
2518 }
2519
2520 if (ops.compType->isUnsignedIntegerType() &&
2521 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
2522 !canElideOverflowCheck(cgf.getContext(), ops))
2523 cgf.cgm.errorNYI("unsigned int overflow sanitizer");
2524
2525 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2526 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2527 // Try to form an fmuladd.
2528 if (mlir::Value fmuladd =
2529 tryEmitFMulAdd(loc, ops, builder, /*isSub=*/true))
2530 return fmuladd;
2531 return builder.createFSub(loc, ops.lhs, ops.rhs);
2532 }
2533
2534 if (ops.isFixedPointOp())
2535 return emitFixedPointBinOp(ops);
2536
2537 return builder.createSub(loc, ops.lhs, ops.rhs);
2538 }
2539
2540 // If the RHS is not a pointer, then we have normal pointer
2541 // arithmetic.
2542 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2543 return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);
2544
2545 // Otherwise, this is a pointer subtraction
2546
2547 // Do the raw subtraction part.
2548 //
2549 // TODO(cir): note for LLVM lowering out of this; when expanding this into
2550 // LLVM we shall take VLA's, division by element size, etc.
2551 //
2552 // See more in `EmitSub` in CGExprScalar.cpp.
2554 return cir::PtrDiffOp::create(builder, cgf.getLoc(ops.loc), cgf.ptrDiffTy,
2555 ops.lhs, ops.rhs);
2556}
2557
2558mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
2559 // TODO: This misses out on the sanitizer check below.
2560 if (ops.isFixedPointOp())
2561 return emitFixedPointBinOp(ops);
2562
2563 // CIR accepts shift between different types, meaning nothing special
2564 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2565 // promote or truncate the RHS to the same size as the LHS.
2566
2567 bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&
2568 ops.compType->hasSignedIntegerRepresentation() &&
2570 !cgf.getLangOpts().CPlusPlus20;
2571 bool sanitizeUnsignedBase =
2572 cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&
2573 ops.compType->hasUnsignedIntegerRepresentation();
2574 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2575 bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);
2576
2577 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2578 if (cgf.getLangOpts().OpenCL)
2579 cgf.cgm.errorNYI("opencl");
2580 else if ((sanitizeBase || sanitizeExponent) &&
2581 mlir::isa<cir::IntType>(ops.lhs.getType()))
2582 cgf.cgm.errorNYI("sanitizers");
2583
2584 return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2585}
2586
2587mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
2588 // TODO: This misses out on the sanitizer check below.
2589 if (ops.isFixedPointOp())
2590 return emitFixedPointBinOp(ops);
2591
2592 // CIR accepts shift between different types, meaning nothing special
2593 // to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
2594 // promote or truncate the RHS to the same size as the LHS.
2595
2596 // OpenCL 6.3j: shift values are effectively % word size of LHS.
2597 if (cgf.getLangOpts().OpenCL)
2598 cgf.cgm.errorNYI("opencl");
2599 else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&
2600 mlir::isa<cir::IntType>(ops.lhs.getType()))
2601 cgf.cgm.errorNYI("sanitizers");
2602
2603 // Note that we don't need to distinguish unsigned treatment at this
2604 // point since it will be handled later by LLVM lowering.
2605 return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2606}
2607
2608mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {
2609 return cir::AndOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2610}
2611mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {
2612 return cir::XorOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2613}
2614mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {
2615 return cir::OrOp::create(builder, cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
2616}
2617
2618// Emit code for an explicit or implicit cast. Implicit
2619// casts have to handle a more broad range of conversions than explicit
2620// casts, as they handle things like function to ptr-to-function decay
2621// etc.
2622mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
2623 Expr *subExpr = ce->getSubExpr();
2624 QualType destTy = ce->getType();
2625 CastKind kind = ce->getCastKind();
2626 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2627
2628 // These cases are generally not written to ignore the result of evaluating
2629 // their sub-expressions, so we clear this now.
2630 ignoreResultAssign = false;
2631
2632 switch (kind) {
2633 case clang::CK_Dependent:
2634 llvm_unreachable("dependent cast kind in CIR gen!");
2635 case clang::CK_BuiltinFnToFnPtr:
2636 llvm_unreachable("builtin functions are handled elsewhere");
2637 case CK_LValueBitCast:
2638 case CK_LValueToRValueBitCast: {
2639 LValue sourceLVal = cgf.emitLValue(subExpr);
2640 Address sourceAddr = sourceLVal.getAddress();
2641
2642 mlir::Type destElemTy = cgf.convertTypeForMem(destTy);
2643 Address destAddr = sourceAddr.withElementType(cgf.getBuilder(), destElemTy);
2644 LValue destLVal = cgf.makeAddrLValue(destAddr, destTy);
2646 return emitLoadOfLValue(destLVal, ce->getExprLoc());
2647 }
2648
2649 case CK_CPointerToObjCPointerCast:
2650 case CK_BlockPointerToObjCPointerCast:
2651 case CK_AnyPointerToBlockPointerCast:
2652 case CK_BitCast: {
2653 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2654 mlir::Type dstTy = cgf.convertType(destTy);
2655
2657
2658 if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
2659 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2660 "sanitizer support");
2661
2662 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2663 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2664 "strict vtable pointers");
2665
2666 // Update heapallocsite metadata when there is an explicit pointer cast.
2668
2669 // If Src is a fixed vector and Dst is a scalable vector, and both have the
2670 // same element type, use the llvm.vector.insert intrinsic to perform the
2671 // bitcast.
2673
2674 // If Src is a scalable vector and Dst is a fixed vector, and both have the
2675 // same element type, use the llvm.vector.extract intrinsic to perform the
2676 // bitcast.
2678
2679 // Perform VLAT <-> VLST bitcast through memory.
2680 // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
2681 // require the element types of the vectors to be the same, we
2682 // need to keep this around for bitcasts between VLAT <-> VLST where
2683 // the element types of the vectors are not the same, until we figure
2684 // out a better way of doing these casts.
2686
2687 return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
2688 src, dstTy);
2689 }
2690 case CK_AddressSpaceConversion: {
2691 Expr::EvalResult result;
2692 if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
2693 result.Val.isNullPointer()) {
2694 // If e has side effect, it is emitted even if its final result is a
2695 // null pointer. In that case, a DCE pass should be able to
2696 // eliminate the useless instructions emitted during translating E.
2697 if (result.HasSideEffects)
2698 Visit(subExpr);
2699 return cgf.cgm.getNullPointer(
2700 mlir::cast<cir::PointerType>(convertType(destTy)), destTy,
2701 cgf.getLoc(subExpr->getExprLoc()));
2702 }
2703 return cgf.performAddrSpaceCast(Visit(subExpr), convertType(destTy));
2704 }
2705
2706 case CK_AtomicToNonAtomic:
2707 case CK_NonAtomicToAtomic:
2708 case CK_UserDefinedConversion:
2709 return Visit(const_cast<Expr *>(subExpr));
2710 case CK_NoOp:
2711 return ce->changesVolatileQualification() ? emitLoadOfLValue(ce)
2712 : Visit(subExpr);
2713 case CK_IntegralToPointer: {
2714 mlir::Type destCIRTy = cgf.convertType(destTy);
2715 mlir::Value src = Visit(const_cast<Expr *>(subExpr));
2716
2717 // Properly resize by casting to an int of the same size as the pointer.
2718 // Clang's IntegralToPointer includes 'bool' as the source, but in CIR
2719 // 'bool' is not an integral type. So check the source type to get the
2720 // correct CIR conversion.
2721 mlir::Type middleTy = cgf.cgm.getDataLayout().getIntPtrType(destCIRTy);
2722 mlir::Value middleVal = builder.createCast(
2723 subExpr->getType()->isBooleanType() ? cir::CastKind::bool_to_int
2724 : cir::CastKind::integral,
2725 src, middleTy);
2726
2727 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) {
2728 cgf.cgm.errorNYI(subExpr->getSourceRange(),
2729 "IntegralToPointer: strict vtable pointers");
2730 return {};
2731 }
2732
2733 return builder.createIntToPtr(middleVal, destCIRTy);
2734 }
2735
2736 case CK_BaseToDerived: {
2737 const CXXRecordDecl *derivedClassDecl = destTy->getPointeeCXXRecordDecl();
2738 assert(derivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
2739 Address base = cgf.emitPointerWithAlignment(subExpr);
2740 Address derived = cgf.getAddressOfDerivedClass(
2741 cgf.getLoc(ce->getSourceRange()), base, derivedClassDecl, ce->path(),
2743
2744 // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
2745 // performed and the object is not of the derived type.
2747
2748 return cgf.getAsNaturalPointerTo(derived, ce->getType()->getPointeeType());
2749 }
2750 case CK_UncheckedDerivedToBase:
2751 case CK_DerivedToBase: {
2752 // The EmitPointerWithAlignment path does this fine; just discard
2753 // the alignment.
2755 ce->getType()->getPointeeType());
2756 }
2757 case CK_Dynamic: {
2758 Address v = cgf.emitPointerWithAlignment(subExpr);
2759 const auto *dce = cast<CXXDynamicCastExpr>(ce);
2760 return cgf.emitDynamicCast(v, dce);
2761 }
2762 case CK_ArrayToPointerDecay:
2763 return cgf.emitArrayToPointerDecay(subExpr).getPointer();
2764
2765 case CK_NullToPointer: {
2766 if (mustVisitNullValue(subExpr))
2767 cgf.emitIgnoredExpr(subExpr);
2768
2769 // Note that DestTy is used as the MLIR type instead of a custom
2770 // nullptr type.
2771 auto ty = mlir::cast<cir::PointerType>(cgf.convertType(destTy));
2772 return cgf.cgm.getNullPointer(ty, destTy,
2773 cgf.getLoc(subExpr->getExprLoc()));
2774 }
2775
2776 case CK_NullToMemberPointer: {
2777 if (mustVisitNullValue(subExpr))
2778 cgf.emitIgnoredExpr(subExpr);
2779
2781
2782 const MemberPointerType *mpt = ce->getType()->getAs<MemberPointerType>();
2783 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2784 return cgf.getBuilder().getConstant(
2785 loc, cgf.cgm.emitNullMemberAttr(destTy, mpt));
2786 }
2787
2788 case CK_ReinterpretMemberPointer: {
2789 mlir::Value src = Visit(subExpr);
2790 return builder.createBitcast(cgf.getLoc(subExpr->getExprLoc()), src,
2791 cgf.convertType(destTy));
2792 }
2793 case CK_BaseToDerivedMemberPointer:
2794 case CK_DerivedToBaseMemberPointer: {
2795 mlir::Value src = Visit(subExpr);
2796
2798
2799 QualType derivedTy =
2800 kind == CK_DerivedToBaseMemberPointer ? subExpr->getType() : destTy;
2801 const auto *mpType = derivedTy->castAs<MemberPointerType>();
2802 NestedNameSpecifier qualifier = mpType->getQualifier();
2803 assert(qualifier && "member pointer without class qualifier");
2804 const Type *qualifierType = qualifier.getAsType();
2805 assert(qualifierType && "member pointer qualifier is not a type");
2806 const CXXRecordDecl *derivedClass = qualifierType->getAsCXXRecordDecl();
2807 CharUnits offset =
2808 cgf.cgm.computeNonVirtualBaseClassOffset(derivedClass, ce->path());
2809
2810 mlir::Location loc = cgf.getLoc(subExpr->getExprLoc());
2811 mlir::Type resultTy = cgf.convertType(destTy);
2812 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.getQuantity());
2813
2814 if (subExpr->getType()->isMemberFunctionPointerType()) {
2815 if (kind == CK_BaseToDerivedMemberPointer)
2816 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2817 offsetAttr);
2818 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2819 }
2820
2821 if (kind == CK_BaseToDerivedMemberPointer)
2822 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2823 offsetAttr);
2824 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2825 offsetAttr);
2826 }
2827
2828 case CK_LValueToRValue:
2829 assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
2830 assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
2831 return Visit(const_cast<Expr *>(subExpr));
2832
2833 case CK_IntegralCast: {
2834 ScalarConversionOpts opts;
2835 if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2836 if (!ice->isPartOfExplicitCast())
2837 opts = ScalarConversionOpts(cgf.sanOpts);
2838 }
2839 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2840 ce->getExprLoc(), opts);
2841 }
2842
2843 case CK_FloatingComplexToReal:
2844 case CK_IntegralComplexToReal:
2845 case CK_FloatingComplexToBoolean:
2846 case CK_IntegralComplexToBoolean: {
2847 mlir::Value value = cgf.emitComplexExpr(subExpr);
2848 return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,
2849 kind, destTy);
2850 }
2851
2852 case CK_FloatingRealToComplex:
2853 case CK_FloatingComplexCast:
2854 case CK_IntegralRealToComplex:
2855 case CK_IntegralComplexCast:
2856 case CK_IntegralComplexToFloatingComplex:
2857 case CK_FloatingComplexToIntegralComplex:
2858 llvm_unreachable("scalar cast to non-scalar value");
2859
2860 case CK_PointerToIntegral: {
2861 assert(!destTy->isBooleanType() && "bool should use PointerToBool");
2862 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
2863 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2864 "strict vtable pointers");
2865 return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));
2866 }
2867 case CK_ToVoid:
2868 cgf.emitIgnoredExpr(subExpr);
2869 return {};
2870
2871 case CK_FixedPointCast:
2872 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2873 ce->getExprLoc());
2874
2875 case CK_FixedPointToBoolean:
2876 assert(subExpr->getType()->isFixedPointType() &&
2877 "Expected src type to be fixed point type");
2878 assert(destTy->isBooleanType() && "Expected dest type to be boolean type");
2879 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2880 ce->getExprLoc());
2881
2882 case CK_FixedPointToIntegral:
2883 assert(subExpr->getType()->isFixedPointType() &&
2884 "Expected src type to be fixed point type");
2885 assert(destTy->isIntegerType() && "Expected dest type to be an integer");
2886 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2887 ce->getExprLoc());
2888
2889 case CK_IntegralToFixedPoint:
2890 assert(subExpr->getType()->isIntegerType() &&
2891 "Expected src type to be an integer");
2892 assert(destTy->isFixedPointType() &&
2893 "Expected dest type to be fixed point type");
2894 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2895 ce->getExprLoc());
2896
2897 case CK_IntegralToFloating:
2898 case CK_FloatingToIntegral:
2899 case CK_FloatingCast:
2900 case CK_FixedPointToFloating:
2901 case CK_FloatingToFixedPoint: {
2902 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2903 return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
2904 ce->getExprLoc());
2905 }
2906
2907 case CK_IntegralToBoolean:
2908 return emitIntToBoolConversion(Visit(subExpr),
2909 cgf.getLoc(ce->getSourceRange()));
2910
2911 case CK_PointerToBoolean:
2912 return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());
2913 case CK_FloatingToBoolean:
2914 return emitFloatToBoolConversion(Visit(subExpr),
2915 cgf.getLoc(subExpr->getExprLoc()));
2916 case CK_MemberPointerToBoolean: {
2917 mlir::Value memPtr = Visit(subExpr);
2918 return builder.createCast(cgf.getLoc(ce->getSourceRange()),
2919 cir::CastKind::member_ptr_to_bool, memPtr,
2920 cgf.convertType(destTy));
2921 }
2922
2923 case CK_VectorSplat: {
2924 // Create a vector object and fill all elements with the same scalar value.
2925 mlir::Type destCIRTy = cgf.convertType(destTy);
2926 assert(mlir::isa<cir::VectorType>(destCIRTy) &&
2927 "CK_VectorSplat to non-vector type");
2928 return cir::VecSplatOp::create(builder,
2929 cgf.getLoc(subExpr->getSourceRange()),
2930 destCIRTy, Visit(subExpr));
2931 }
2932 case CK_FunctionToPointerDecay:
2933 return cgf.emitLValue(subExpr).getPointer();
2934
2935 default:
2936 cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
2937 "CastExpr: ", ce->getCastKindName());
2938 }
2939 return {};
2940}
2941
2942mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
2944 return emitLoadOfLValue(e);
2945
2946 auto v = cgf.emitCallExpr(e).getValue();
2948 return v;
2949}
2950
2951mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2952 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e)) {
2953 cgf.emitIgnoredExpr(e->getBase());
2954 return cgf.emitScalarConstant(constant, e);
2955 } else {
2956 Expr::EvalResult result;
2957 if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {
2958 llvm::APSInt value = result.Val.getInt();
2959 cgf.emitIgnoredExpr(e->getBase());
2960 mlir::Location loc = cgf.getLoc(e->getExprLoc());
2961 // The constant is folded from an APSInt with the source-type's bit width
2962 // (1 for bool), but the AST's expression type is what later consumers of
2963 // this value see. For a bool member we have to emit a !cir.bool constant
2964 // -- otherwise downstream ops (cir.call into a bool parameter, cir.if /
2965 // cir.ternary on the value, ...) would all reject the !cir.int<u, 1> the
2966 // raw APSInt would produce.
2967 if (e->getType()->isBooleanType())
2968 return builder.getBool(value.getBoolValue(), loc);
2969 return builder.getConstInt(loc, value);
2970 }
2971 }
2972
2973 return emitLoadOfLValue(e);
2974}
2975
2976mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2977 const unsigned numInitElements = e->getNumInits();
2978
2979 [[maybe_unused]] const bool ignore = std::exchange(ignoreResultAssign, false);
2980 assert((ignore == false ||
2981 (numInitElements == 0 && e->getType()->isVoidType())) &&
2982 "init list ignored");
2983
2984 if (e->hadArrayRangeDesignator()) {
2985 cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
2986 return {};
2987 }
2988
2989 if (e->getType()->isVectorType()) {
2990 const auto vectorType =
2991 mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
2992
2993 SmallVector<mlir::Value, 16> elements;
2994 for (Expr *init : e->inits()) {
2995 elements.push_back(Visit(init));
2996 }
2997
2998 // Zero-initialize any remaining values.
2999 if (numInitElements < vectorType.getSize()) {
3000 const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
3001 vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
3002 std::fill_n(std::back_inserter(elements),
3003 vectorType.getSize() - numInitElements, zeroValue);
3004 }
3005
3006 return cir::VecCreateOp::create(cgf.getBuilder(),
3007 cgf.getLoc(e->getSourceRange()), vectorType,
3008 elements);
3009 }
3010
3011 if (e->getType()->isVoidType())
3012 return {};
3013
3014 // C++11 value-initialization for the scalar.
3015 if (numInitElements == 0)
3016 return emitNullValue(e->getType(), cgf.getLoc(e->getExprLoc()));
3017
3018 return Visit(e->getInit(0));
3019}
3020
3021mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
3022 QualType srcTy, QualType dstTy,
3023 SourceLocation loc) {
3026 "Invalid scalar expression to emit");
3027 return ScalarExprEmitter(*this, builder)
3028 .emitScalarConversion(src, srcTy, dstTy, loc);
3029}
3030
3032 QualType srcTy,
3033 QualType dstTy,
3034 SourceLocation loc) {
3035 assert(srcTy->isAnyComplexType() && hasScalarEvaluationKind(dstTy) &&
3036 "Invalid complex -> scalar conversion");
3037
3038 QualType complexElemTy = srcTy->castAs<ComplexType>()->getElementType();
3039 if (dstTy->isBooleanType()) {
3040 auto kind = complexElemTy->isFloatingType()
3041 ? cir::CastKind::float_complex_to_bool
3042 : cir::CastKind::int_complex_to_bool;
3043 return builder.createCast(getLoc(loc), kind, src, convertType(dstTy));
3044 }
3045
3046 auto kind = complexElemTy->isFloatingType()
3047 ? cir::CastKind::float_complex_to_real
3048 : cir::CastKind::int_complex_to_real;
3049 mlir::Value real =
3050 builder.createCast(getLoc(loc), kind, src, convertType(complexElemTy));
3051 return emitScalarConversion(real, complexElemTy, dstTy, loc);
3052}
3053
3054mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
3055 // Perform vector logical not on comparison with zero vector.
3056 if (e->getType()->isVectorType() &&
3057 e->getType()->castAs<VectorType>()->getVectorKind() ==
3059 mlir::Value oper = Visit(e->getSubExpr());
3060 mlir::Location loc = cgf.getLoc(e->getExprLoc());
3061 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
3062 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
3063 auto resultTy = mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
3064 return builder.createVecCompare(loc, resultTy, cir::CmpOpKind::eq, oper,
3065 zeroVec);
3066 }
3067
3068 // Compare operand to zero.
3069 mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());
3070
3071 // Invert value.
3072 boolVal = builder.createNot(boolVal);
3073
3074 // ZExt result to the expr type.
3075 return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
3076}
3077
3078mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {
3079 // Try folding the offsetof to a constant.
3080 Expr::EvalResult evalResult;
3081 if (e->EvaluateAsInt(evalResult, cgf.getContext())) {
3082 mlir::Type type = cgf.convertType(e->getType());
3083 llvm::APSInt value = evalResult.Val.getInt();
3084 return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);
3085 }
3086
3088 e->getSourceRange(),
3089 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
3090 return {};
3091}
3092
3093mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
3094 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
3095 mlir::Value result = VisitRealImag(e, promotionTy);
3096 if (result && !promotionTy.isNull())
3097 result = emitUnPromotedValue(result, e->getType());
3098 return result;
3099}
3100
3101mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {
3102 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
3103 mlir::Value result = VisitRealImag(e, promotionTy);
3104 if (result && !promotionTy.isNull())
3105 result = emitUnPromotedValue(result, e->getType());
3106 return result;
3107}
3108
3109mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
3110 QualType promotionTy) {
3111 assert(
3112 (e->getOpcode() == clang::UO_Real || e->getOpcode() == clang::UO_Imag) &&
3113 "Invalid UnaryOp kind for ComplexType Real or Imag");
3114
3115 Expr *op = e->getSubExpr();
3116 mlir::Location loc = cgf.getLoc(e->getExprLoc());
3117 if (op->getType()->isAnyComplexType()) {
3118 // If it's an l-value, load through the appropriate subobject l-value.
3119 // Note that we have to ask `e` because `op` might be an l-value that
3120 // this won't work for, e.g. an Obj-C property
3121 mlir::Value complex = cgf.emitComplexExpr(op);
3122 if (e->isGLValue() && !promotionTy.isNull()) {
3123 promotionTy = promotionTy->isAnyComplexType()
3124 ? promotionTy
3125 : cgf.getContext().getComplexType(promotionTy);
3126 complex = cgf.emitPromotedValue(complex, promotionTy);
3127 }
3128
3129 return e->getOpcode() == clang::UO_Real
3130 ? builder.createComplexReal(loc, complex)
3131 : builder.createComplexImag(loc, complex);
3132 }
3133
3134 if (e->getOpcode() == UO_Real) {
3135 mlir::Value operand = promotionTy.isNull()
3136 ? Visit(op)
3137 : cgf.emitPromotedScalarExpr(op, promotionTy);
3138 return builder.createComplexReal(loc, operand);
3139 }
3140
3141 // __imag on a scalar returns zero. Emit the subexpr to ensure side
3142 // effects are evaluated, but not the actual value.
3143 mlir::Value operand;
3144 if (op->isGLValue()) {
3145 operand = cgf.emitLValue(op).getPointer();
3146 operand = cir::LoadOp::create(builder, loc, operand);
3147 } else if (!promotionTy.isNull()) {
3148 operand = cgf.emitPromotedScalarExpr(op, promotionTy);
3149 } else {
3150 operand = cgf.emitScalarExpr(op);
3151 }
3152 return builder.createComplexImag(loc, operand);
3153}
3154
3155/// Return the size or alignment of the type of argument of the sizeof
3156/// expression as an integer.
3157mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
3158 const UnaryExprOrTypeTraitExpr *e) {
3159 const QualType typeToSize = e->getTypeOfArgument();
3160 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
3161 if (auto kind = e->getKind();
3162 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
3163 if (const VariableArrayType *vat =
3164 cgf.getContext().getAsVariableArrayType(typeToSize)) {
3165 // For _Countof, we only want to evaluate if the extent is actually
3166 // variable as opposed to a multi-dimensional array whose extent is
3167 // constant but whose element type is variable.
3168 bool evaluateExtent = true;
3169 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3170 evaluateExtent =
3171 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.getContext());
3172 }
3173
3174 if (evaluateExtent) {
3175 if (e->isArgumentType()) {
3176 // sizeof(type) - make sure to emit the VLA size.
3177 cgf.emitVariablyModifiedType(typeToSize);
3178 } else {
3179 // C99 6.5.3.4p2: If the argument is an expression of type
3180 // VLA, it is evaluated.
3182 }
3183
3184 // For _Countof, we just want to return the size of a single dimension.
3185 if (kind == UETT_CountOf)
3186 return cgf.getVLAElements1D(vat).numElts;
3187
3188 // For sizeof and __datasizeof, we need to scale the number of elements
3189 // by the size of the array element type.
3190 CIRGenFunction::VlaSizePair vlaSize = cgf.getVLASize(vat);
3191 mlir::Value numElts = vlaSize.numElts;
3192
3193 // Scale the number of non-VLA elements by the non-VLA element size.
3194 CharUnits eltSize = cgf.getContext().getTypeSizeInChars(vlaSize.type);
3195 if (!eltSize.isOne()) {
3196 mlir::Location loc = cgf.getLoc(e->getSourceRange());
3197 mlir::Value eltSizeValue =
3198 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
3199 cgf.cgm.getSize(eltSize).getValue());
3200 return builder.createMul(loc, eltSizeValue, numElts,
3202 }
3203
3204 return numElts;
3205 }
3206 }
3207 } else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
3209 cgf.getContext()
3212 .getQuantity();
3213 return builder.getConstantInt(loc, cgf.cgm.sizeTy, alignment);
3214 } else if (e->getKind() == UETT_VectorElements) {
3215 auto vecTy = cast<cir::VectorType>(convertType(e->getTypeOfArgument()));
3216 if (vecTy.getIsScalable()) {
3218 e->getSourceRange(),
3219 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3220 return builder.getConstant(
3221 loc, cir::IntAttr::get(cgf.cgm.sizeTy,
3223 }
3224
3225 return builder.getConstant(
3226 loc, cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getSize()));
3227 }
3228
3229 // The result type is size_t (target-dependent width); use it so the IntAttr
3230 // width matches the APInt from EvaluateKnownConstInt.
3231 return builder.getConstant(
3232 loc, cir::IntAttr::get(cgf.cgm.sizeTy,
3234}
3235
3236mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3237 const AbstractConditionalOperator *e) {
3238 CIRGenBuilderTy &builder = cgf.getBuilder();
3239 mlir::Location loc = cgf.getLoc(e->getSourceRange());
3240 ignoreResultAssign = false;
3241
3242 // Bind the common expression if necessary.
3243 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3244
3245 Expr *condExpr = e->getCond();
3246 Expr *lhsExpr = e->getTrueExpr();
3247 Expr *rhsExpr = e->getFalseExpr();
3248
3249 // If the condition constant folds and can be elided, try to avoid emitting
3250 // the condition and the dead arm.
3251 bool condExprBool;
3252 if (cgf.constantFoldsToBool(condExpr, condExprBool)) {
3253 Expr *live = lhsExpr, *dead = rhsExpr;
3254 if (!condExprBool)
3255 std::swap(live, dead);
3256
3257 // If the dead side doesn't have labels we need, just emit the Live part.
3258 if (!cgf.containsLabel(dead)) {
3259 if (condExprBool)
3261 mlir::Value result = Visit(live);
3262
3263 // If the live part is a throw expression, it acts like it has a void
3264 // type, so evaluating it returns a null Value. However, a conditional
3265 // with non-void type must return a non-null Value.
3266 if (!result && !e->getType()->isVoidType()) {
3267 result = builder.getConstant(
3268 loc, cir::PoisonAttr::get(builder.getContext(),
3269 cgf.convertType(e->getType())));
3270 }
3271
3272 return result;
3273 }
3274 }
3275
3276 QualType condType = condExpr->getType();
3277
3278 // OpenCL: If the condition is a vector, we can treat this condition like
3279 // the select function.
3280 if (cgf.getLangOpts().OpenCL &&
3281 (condType->isVectorType() || condType->isExtVectorType())) {
3283
3284 mlir::Value condValue = cgf.emitScalarExpr(condExpr);
3285 mlir::Value lhsValue = Visit(lhsExpr);
3286 mlir::Value rhsValue = Visit(rhsExpr);
3287
3288 mlir::Type vecTy = convertType(condType);
3289 mlir::Value zeroVec = builder.getNullValue(vecTy, loc);
3290 auto testMSB = cir::VecCmpOp::create(
3291 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3292 mlir::Value tmp = builder.createIntCast(testMSB, vecTy);
3293 mlir::Value tmp2 = builder.createNot(tmp);
3294
3295 // Cast float to int to perform ANDs if necessary.
3296 mlir::Value rhsTmp = rhsValue;
3297 mlir::Value lhsTmp = lhsValue;
3298 bool wasCast = false;
3299 auto rhsVecTy = cast<cir::VectorType>(rhsValue.getType());
3300 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
3301 rhsTmp = builder.createBitcast(rhsValue, tmp2.getType());
3302 lhsTmp = builder.createBitcast(lhsValue, tmp.getType());
3303 wasCast = true;
3304 }
3305
3306 mlir::Value tmp3 = builder.createAnd(loc, rhsTmp, tmp2);
3307 mlir::Value tmp4 = builder.createAnd(loc, lhsTmp, tmp);
3308 mlir::Value tmp5 = builder.createOr(loc, tmp3, tmp4);
3309 if (wasCast)
3310 tmp5 = builder.createBitcast(tmp5, rhsValue.getType());
3311 return tmp5;
3312 }
3313
3314 if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {
3315 if (!condType->isVectorType()) {
3317 cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");
3318 return {};
3319 }
3320
3321 mlir::Value condValue = Visit(condExpr);
3322 mlir::Value lhsValue = Visit(lhsExpr);
3323 mlir::Value rhsValue = Visit(rhsExpr);
3324 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3325 rhsValue);
3326 }
3327
3328 // If this is a really simple expression (like x ? 4 : 5), emit this as a
3329 // select instead of as control flow. We can only do this if it is cheap
3330 // and safe to evaluate the LHS and RHS unconditionally.
3332 cgf.getContext()) &&
3334 cgf.getContext())) {
3335 mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
3337
3338 mlir::Value lhs = Visit(lhsExpr);
3339 mlir::Value rhs = Visit(rhsExpr);
3340 if (!lhs) {
3341 // If the conditional has void type, make sure we return a null Value.
3342 assert(!rhs && "lhs and rhs types must match");
3343 return {};
3344 }
3345
3346 return builder.createSelect(loc, condV, lhs, rhs);
3347 }
3348
3349 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);
3350 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
3351
3352 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {
3353 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3355
3356 mlir::Value branch;
3357 {
3358 // Emit any cleanups that were needed on this branch so we can spill
3359 // and reload the return value.
3360 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3362 eval.beginEvaluation();
3363 branch = Visit(expr);
3364 eval.endEvaluation();
3365 branchCleanups.forceCleanup({&branch});
3366 }
3367
3368 if (branch)
3369 cir::YieldOp::create(b, loc, branch);
3370 };
3371
3372 cir::TernaryOp ternary = cir::TernaryOp::create(
3373 builder, loc, condV,
3374 /*trueBuilder=*/
3375 [&](mlir::OpBuilder &b, mlir::Location loc) {
3376 emitBranch(b, loc, lhsExpr);
3377 },
3378 /*falseBuilder=*/
3379 [&](mlir::OpBuilder &b, mlir::Location loc) {
3380 emitBranch(b, loc, rhsExpr);
3381 });
3382
3383 // Only a void arm can be left unterminated (a noreturn arm already ends
3384 // in cir.unreachable); close it with an empty cir.yield.
3385 for (mlir::Region *region :
3386 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3387 mlir::Block &lastBlock = region->back();
3388 if (lastBlock.empty() ||
3389 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3390 mlir::OpBuilder::InsertionGuard guard(builder);
3391 builder.setInsertionPointToEnd(&lastBlock);
3392 cir::YieldOp::create(builder, loc);
3393 }
3394 }
3395
3396 return ternary.getResult();
3397}
3398
3400 LValue lv) {
3401 return ScalarExprEmitter(*this, builder).emitScalarPrePostIncDec(e, lv);
3402}
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
#define HANDLE_BINOP(OP)
static bool mustVisitNullValue(const Expr *e)
#define COMPOUND_OP(Op)
#define HANDLEBINOP(OP)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op, CIRGenBuilderTy &builder, bool isSub=false)
static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp, mlir::Value addend, CIRGenBuilderTy &builder, bool negMul, bool negAdd)
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
#define VISITCOMP(CODE)
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
Compares lhs and rhs element-wise.
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
APSInt & getInt()
Definition APValue.h:573
bool isNullPointer() const
Definition APValue.cpp:1162
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
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.
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const
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:4579
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4585
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4591
LabelDecl * getLabel() const
Definition Expr.h:4621
uint64_t getValue() const
Definition ExprCXX.h:3059
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
Definition Expr.h:6806
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4086
Expr * getLHS() const
Definition Expr.h:4136
SourceLocation getExprLoc() const
Definition Expr.h:4127
bool isShiftOp() const
Definition Expr.h:4175
Expr * getRHS() const
Definition Expr.h:4138
bool isShiftAssignOp() const
Definition Expr.h:4244
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:4299
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:2242
Opcode getOpcode() const
Definition Expr.h:4131
BinaryOperatorKind Opcode
Definition Expr.h:4091
mlir::Value getPointer() const
Definition Address.h:98
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
std::pair< mlir::Value, mlir::Value > splatMatrixOpOperandsIfNecessary(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
cir::MatrixMultiplyOp createMatrixMultiply(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
Multiply an MxK matrix by a KxN matrix, producing an MxN matrix.
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
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
mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e)
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)
mlir::Value getNullPointer(cir::PointerType ptrTy, QualType qt, mlir::Location loc)
Get target specific null pointer.
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)
cir::GlobalOp createGlobalString(mlir::Location loc, llvm::StringRef str, llvm::StringRef name)
Create a private constant global holding the null-terminated string str, mirroring llvm::IRBuilder::C...
const cir::CIRDataLayout & getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Value 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:745
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1137
bool getValue() const
Definition ExprCXX.h:4386
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:309
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1635
CastKind getCastKind() const
Definition Expr.h:3768
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3811
bool changesVolatileQualification() const
Return.
Definition Expr.h:3858
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1987
Expr * getSubExpr()
Definition Expr.h:3774
int64_t QuantityType
Definition CharUnits.h:40
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
bool isOne() const
Test whether the quantity equals one.
Definition CharUnits.h:104
unsigned getValue() const
Definition Expr.h:1653
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4932
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3362
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4348
QualType getComputationLHSType() const
Definition Expr.h:4382
QualType getComputationResultType() const
Definition Expr.h:4385
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:4857
ChildElementIter< false > begin()
Definition Expr.h:5289
size_t getDataElementCount() const
Definition Expr.h:5205
This represents one expression.
Definition Expr.h:113
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:288
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:695
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:3125
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:3109
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
bool allowFPContractWithinStatement() const
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
Definition Expr.h:1599
llvm::APFloat getValue() const
Definition Expr.h:1690
const Expr * getSubExpr() const
Definition Expr.h:1086
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6522
unsigned getNumInits() const
Definition Expr.h:5389
bool hadArrayRangeDesignator() const
Definition Expr.h:5537
const Expr * getInit(unsigned Init) const
Definition Expr.h:5411
ArrayRef< Expr * > inits() const
Definition Expr.h:5409
bool isSignedOverflowDefined() const
Expr * getBase() const
Definition Expr.h:3489
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3607
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:247
SourceRange getSourceRange() const
Definition ExprObjC.h:1754
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:189
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:414
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2575
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:1232
Expr * getSelectedExpr() const
Definition ExprCXX.h:4693
const Expr * getSubExpr() const
Definition Expr.h:2247
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3403
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1454
QualType getCanonicalType() const
Definition TypeBase.h:8498
bool UseExcessPrecision(const ASTContext &Ctx)
Definition Type.cpp:1775
bool isCanonical() const
Definition TypeBase.h:8503
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:362
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:355
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:351
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:365
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:368
bool isSatisfied() const
Whether or not the requires clause is satisfied.
std::string ComputeName(ASTContext &Context) const
Definition Expr.cpp:597
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Definition Expr.h:4724
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
Definition Expr.h:4730
unsigned getPackLength() const
Retrieve the length of the parameter pack.
Definition ExprCXX.h:4569
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:2319
SourceLocation getLocation() const
Definition Expr.h:5118
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
Definition Expr.h:4660
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:2962
const APValue & getAPValue() const
Definition ExprCXX.h:2967
bool isStoredAsBoolean() const
Definition ExprCXX.h:2954
bool isVoidType() const
Definition TypeBase.h:9068
bool isBooleanType() const
Definition TypeBase.h:9209
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2415
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2392
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:8850
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9116
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9366
bool isReferenceType() const
Definition TypeBase.h:8707
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:2080
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
Definition Type.cpp:2829
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2504
bool isExtVectorType() const
Definition TypeBase.h:8826
bool isExtVectorBoolType() const
Definition TypeBase.h:8830
bool isAnyComplexType() const
Definition TypeBase.h:8818
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition TypeBase.h:9132
bool isHalfType() const
Definition TypeBase.h:9076
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2436
bool isMatrixType() const
Definition TypeBase.h:8846
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2881
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8768
bool isVectorType() const
Definition TypeBase.h:8822
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2533
bool isFloatingType() const
Definition Type.cpp:2517
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:2460
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isNullPtrType() const
Definition TypeBase.h:9109
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2742
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2705
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2292
SourceLocation getExprLoc() const
Definition Expr.h:2416
Expr * getSubExpr() const
Definition Expr.h:2333
Opcode getOpcode() const
Definition Expr.h:2328
static bool isIncrementOp(Opcode Op)
Definition Expr.h:2374
static bool isDecrementOp(Opcode Op)
Definition Expr.h:2381
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:2448
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2367
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Definition Expr.h:2346
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4064
Represents a GCC generic vector type.
Definition TypeBase.h:4273
VectorKind getVectorKind() const
Definition TypeBase.h:4293
OverflowBehavior
bool isCheapEnoughToEvaluateUnconditionally(const Expr *E, const ASTContext &Ctx)
Check whether E is cheap enough and side-effect-free enough to evaluate unconditionally instead of co...
Definition ExprUtils.cpp:87
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Definition Utils.h:57
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
Definition TypeBase.h:4234
U cast(CodeGen::Address addr)
Definition Address.h:327
long int64_t
#define false
Definition stdbool.h:26
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool emitMatrixIndexAssumption()
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:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
bool HasSideEffects
Whether the evaluated expression has side effects.
Definition Expr.h:625
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
Definition Sanitizers.h:174