clang 23.0.0git
CIRGenExprComplex.cpp
Go to the documentation of this file.
1#include "CIRGenBuilder.h"
3#include "CIRGenFunction.h"
4
6
7using namespace clang;
8using namespace clang::CIRGen;
9
10#ifndef NDEBUG
11/// Return the complex type that we are meant to emit.
13 type = type.getCanonicalType();
14 if (const ComplexType *comp = dyn_cast<ComplexType>(type))
15 return comp;
16 return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
17}
18#endif // NDEBUG
19
20namespace {
21class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
22 CIRGenFunction &cgf;
23 CIRGenBuilderTy &builder;
24
25public:
26 explicit ComplexExprEmitter(CIRGenFunction &cgf)
27 : cgf(cgf), builder(cgf.getBuilder()) {}
28
29 //===--------------------------------------------------------------------===//
30 // Utilities
31 //===--------------------------------------------------------------------===//
32
33 /// Given an expression with complex type that represents a value l-value,
34 /// this method emits the address of the l-value, then loads and returns the
35 /// result.
36 mlir::Value emitLoadOfLValue(const Expr *e) {
37 return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());
38 }
39
40 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
41
42 /// Store the specified real/imag parts into the
43 /// specified value pointer.
44 void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
45 bool isInit);
46
47 /// Emit a cast from complex value Val to DestType.
48 mlir::Value emitComplexToComplexCast(mlir::Value value, QualType srcType,
49 QualType destType, SourceLocation loc);
50
51 /// Emit a cast from scalar value Val to DestType.
52 mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType,
53 QualType destType, SourceLocation loc);
54
55 //===--------------------------------------------------------------------===//
56 // Visitor Methods
57 //===--------------------------------------------------------------------===//
58
59 mlir::Value Visit(Expr *e) {
60 return StmtVisitor<ComplexExprEmitter, mlir::Value>::Visit(e);
61 }
62
63 mlir::Value VisitStmt(Stmt *s) {
64 cgf.cgm.errorNYI(s->getBeginLoc(), "ComplexExprEmitter VisitStmt");
65 return {};
66 }
67
68 mlir::Value VisitExpr(Expr *e);
69 mlir::Value VisitConstantExpr(ConstantExpr *e) {
70 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e))
71 return builder.getConstant(cgf.getLoc(e->getSourceRange()),
72 mlir::cast<mlir::TypedAttr>(result));
73
74 cgf.cgm.errorNYI(e->getExprLoc(),
75 "ComplexExprEmitter VisitConstantExpr non constantexpr");
76 return {};
77 }
78
79 mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
80 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
81 return Visit(ge->getResultExpr());
82 }
83 mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
84 mlir::Value
85 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe) {
86 return Visit(pe->getReplacement());
87 }
88 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
89 cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr");
90 return {};
91 }
92 mlir::Value VisitCoyieldExpr(CoyieldExpr *s) {
93 cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr");
94 return {};
95 }
96 mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
97 cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait");
98 return {};
99 }
100
101 mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,
102 Expr *e) {
103 assert(constant && "not a constant");
104 if (constant.isReference())
105 return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),
106 e->getExprLoc());
107
108 mlir::TypedAttr valueAttr = constant.getValue();
109 return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);
110 }
111
112 // l-values.
113 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
114 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
115 return emitConstant(constant, e);
116 return emitLoadOfLValue(e);
117 }
118 mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) {
119 cgf.cgm.errorNYI(e->getExprLoc(),
120 "ComplexExprEmitter VisitObjCIvarRefExpr");
121 return {};
122 }
123 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
124 cgf.cgm.errorNYI(e->getExprLoc(),
125 "ComplexExprEmitter VisitObjCMessageExpr");
126 return {};
127 }
128 mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); }
129 mlir::Value VisitMemberExpr(MemberExpr *me) {
130 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
131 cgf.emitIgnoredExpr(me->getBase());
132 return emitConstant(constant, me);
133 }
134 return emitLoadOfLValue(me);
135 }
136 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
137 if (e->isGLValue())
138 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
139 e->getExprLoc());
140 return cgf.getOrCreateOpaqueRValueMapping(e).getComplexValue();
141 }
142
143 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
144 cgf.cgm.errorNYI(e->getExprLoc(),
145 "ComplexExprEmitter VisitPseudoObjectExpr");
146 return {};
147 }
148
149 mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
150 mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e) {
151 // Unlike for scalars, we don't have to worry about function->ptr demotion
152 // here.
154 return emitLoadOfLValue(e);
155 return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
156 }
157 mlir::Value VisitCastExpr(CastExpr *e) {
158 if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) {
159 // Bind VLAs in the cast type.
160 if (ece->getType()->isVariablyModifiedType()) {
161 cgf.cgm.errorNYI(e->getExprLoc(),
162 "VisitCastExpr Bind VLAs in the cast type");
163 return {};
164 }
165 }
166
168 return emitLoadOfLValue(e);
169
170 return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
171 }
172 mlir::Value VisitCallExpr(const CallExpr *e);
173 mlir::Value VisitStmtExpr(const StmtExpr *e);
174
175 // Operators.
176 mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op,
177 bool isPre) {
178 LValue lv = cgf.emitLValue(e->getSubExpr());
179 return cgf.emitComplexPrePostIncDec(e, lv, op, isPre);
180 }
181 mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
182 return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false);
183 }
184 mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
185 return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false);
186 }
187 mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
188 return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true);
189 }
190 mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
191 return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true);
192 }
193 mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }
194
195 mlir::Value VisitUnaryPlus(const UnaryOperator *e);
196 mlir::Value VisitUnaryMinus(const UnaryOperator *e);
197 mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind,
198 QualType promotionType);
199 mlir::Value VisitUnaryNot(const UnaryOperator *e);
200 // LNot,Real,Imag never return complex.
201 mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
202 return Visit(e->getSubExpr());
203 }
204 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
205 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
206 return Visit(dae->getExpr());
207 }
208 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
209 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
210 return Visit(die->getExpr());
211 }
212 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) {
213 CIRGenFunction::RunCleanupsScope scope(cgf);
214 mlir::Value complexVal = Visit(e->getSubExpr());
215 // Defend against dominance problems caused by jumps out of expression
216 // evaluation through the shared cleanup block.
217 scope.forceCleanup();
218 return complexVal;
219 }
220 mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
221 mlir::Location loc = cgf.getLoc(e->getExprLoc());
222 mlir::Type complexTy = cgf.convertType(e->getType());
223 return builder.getNullValue(complexTy, loc);
224 }
225 mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
226 cgf.cgm.errorNYI(e->getExprLoc(),
227 "ComplexExprEmitter VisitImplicitValueInitExpr");
228 return {};
229 }
230
231 struct BinOpInfo {
232 mlir::Location loc;
233 mlir::Value lhs{};
234 mlir::Value rhs{};
235 QualType ty{}; // Computation Type.
236 FPOptions fpFeatures{};
237 };
238
239 BinOpInfo emitBinOps(const BinaryOperator *e,
240 QualType promotionTy = QualType());
241
242 mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
243 mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
244 LValue emitCompoundAssignLValue(
245 const CompoundAssignOperator *e,
246 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
247 RValue &value);
248 mlir::Value emitCompoundAssign(
249 const CompoundAssignOperator *e,
250 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
251
252 mlir::Value emitBinAdd(const BinOpInfo &op);
253 mlir::Value emitBinSub(const BinOpInfo &op);
254 mlir::Value emitBinMul(const BinOpInfo &op);
255 mlir::Value emitBinDiv(const BinOpInfo &op);
256
257 QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
258 if (auto *complexTy = ty->getAs<ComplexType>()) {
259 QualType elementTy = complexTy->getElementType();
260 if (elementTy.UseExcessPrecision(cgf.getContext()))
261 return cgf.getContext().getComplexType(cgf.getContext().FloatTy);
262 }
263
264 if (ty.UseExcessPrecision(cgf.getContext()))
265 return cgf.getContext().FloatTy;
266 return QualType();
267 }
268
269#define HANDLEBINOP(OP) \
270 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
271 QualType promotionTy = getPromotionType( \
272 e->getType(), e->getOpcode() == BinaryOperatorKind::BO_Div); \
273 mlir::Value result = emitBin##OP(emitBinOps(e, promotionTy)); \
274 if (!promotionTy.isNull()) \
275 result = cgf.emitUnPromotedValue(result, e->getType()); \
276 return result; \
277 }
278
279 HANDLEBINOP(Add)
280 HANDLEBINOP(Sub)
281 HANDLEBINOP(Mul)
282 HANDLEBINOP(Div)
283#undef HANDLEBINOP
284
285 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
286 cgf.cgm.errorNYI(e->getExprLoc(),
287 "ComplexExprEmitter VisitCXXRewrittenBinaryOperator");
288 return {};
289 }
290
291 // Compound assignments.
292 mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
293 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
294 }
295 mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
296 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
297 }
298 mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) {
299 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul);
300 }
301 mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) {
302 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv);
303 }
304
305 // GCC rejects rem/and/or/xor for integer complex.
306 // Logical and/or always return int, never complex.
307
308 // No comparisons produce a complex result.
309
310 LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
311 mlir::Value VisitBinAssign(const BinaryOperator *e);
312 mlir::Value VisitBinComma(const BinaryOperator *e);
313
314 mlir::Value
315 VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
316 mlir::Value VisitChooseExpr(ChooseExpr *e);
317
318 mlir::Value VisitInitListExpr(InitListExpr *e);
319
320 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
321 return emitLoadOfLValue(e);
322 }
323
324 mlir::Value VisitVAArgExpr(VAArgExpr *e);
325
326 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
327 return cgf.emitAtomicExpr(e).getComplexValue();
328 }
329
330 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
331 cgf.cgm.errorNYI(e->getExprLoc(),
332 "ComplexExprEmitter VisitPackIndexingExpr");
333 return {};
334 }
335};
336} // namespace
337
338//===----------------------------------------------------------------------===//
339// Utilities
340//===----------------------------------------------------------------------===//
341
342/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
343/// load the real and imaginary pieces, returning them as Real/Imag.
344mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
345 SourceLocation loc) {
346 assert(lv.isSimple() && "non-simple complex l-value?");
347 if (lv.getType()->isAtomicType())
348 cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");
349
350 const Address srcAddr = lv.getAddress();
351 return builder.createLoad(cgf.getLoc(loc), srcAddr, lv.isVolatileQualified());
352}
353
354/// EmitStoreOfComplex - Store the specified real/imag parts into the
355/// specified value pointer.
356void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
357 LValue lv, bool isInit) {
358 if (lv.getType()->isAtomicType() ||
359 (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
360 cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");
361 return;
362 }
363
364 const Address destAddr = lv.getAddress();
365 builder.createStore(loc, val, destAddr, lv.isVolatileQualified());
366}
367
368//===----------------------------------------------------------------------===//
369// Visitor Methods
370//===----------------------------------------------------------------------===//
371
372mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) {
373 cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
374 return {};
375}
376
377mlir::Value
378ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
379 auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
380 mlir::Type elementTy = ty.getElementType();
381 mlir::Location loc = cgf.getLoc(il->getExprLoc());
382
383 mlir::TypedAttr realValueAttr;
384 mlir::TypedAttr imagValueAttr;
385
386 if (mlir::isa<cir::IntType>(elementTy)) {
387 llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
388 realValueAttr = cir::IntAttr::get(elementTy, 0);
389 imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
390 } else {
391 assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
392 "Expected complex element type to be floating-point");
393
394 llvm::APFloat imagValue =
395 cast<FloatingLiteral>(il->getSubExpr())->getValue();
396 realValueAttr = cir::FPAttr::get(
397 elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
398 imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
399 }
400
401 auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
402 return cir::ConstantOp::create(builder, loc, complexAttr);
403}
404
405mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
407 return emitLoadOfLValue(e);
408 return cgf.emitCallExpr(e).getComplexValue();
409}
410
411mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
412 CIRGenFunction::StmtExprEvaluation eval(cgf);
413 Address retAlloca =
414 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
415 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
416 assert(retAlloca.isValid() && "Expected complex return value");
417 return emitLoadOfLValue(cgf.makeAddrLValue(retAlloca, e->getType()),
418 e->getExprLoc());
419}
420
421mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
422 QualType srcType,
423 QualType destType,
424 SourceLocation loc) {
425 if (srcType == destType)
426 return val;
427
428 // Get the src/dest element type.
429 QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType();
430 QualType destElemTy = destType->castAs<ComplexType>()->getElementType();
431
432 cir::CastKind castOpKind;
433 if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
434 castOpKind = cir::CastKind::float_complex;
435 else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
436 castOpKind = cir::CastKind::float_complex_to_int_complex;
437 else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
438 castOpKind = cir::CastKind::int_complex_to_float_complex;
439 else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
440 castOpKind = cir::CastKind::int_complex;
441 else
442 llvm_unreachable("unexpected src type or dest type");
443
444 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
445 cgf.convertType(destType));
446}
447
448mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
449 QualType srcType,
450 QualType destType,
451 SourceLocation loc) {
452 cir::CastKind castOpKind;
453 if (srcType->isFloatingType())
454 castOpKind = cir::CastKind::float_to_complex;
455 else if (srcType->isIntegerType())
456 castOpKind = cir::CastKind::int_to_complex;
457 else
458 llvm_unreachable("unexpected src type");
459
460 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
461 cgf.convertType(destType));
462}
463
464mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
465 QualType destTy) {
466 switch (ck) {
467 case CK_Dependent:
468 llvm_unreachable("dependent type must be resolved before the CIR codegen");
469
470 case CK_NoOp:
471 case CK_LValueToRValue:
472 return Visit(op);
473
474 case CK_AtomicToNonAtomic:
475 case CK_NonAtomicToAtomic:
476 case CK_UserDefinedConversion: {
477 cgf.cgm.errorNYI(
478 "ComplexExprEmitter::emitCast Atmoic & UserDefinedConversion");
479 return {};
480 }
481
482 case CK_LValueBitCast: {
483 LValue origLV = cgf.emitLValue(op);
484 Address addr =
485 origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
486 LValue destLV = cgf.makeAddrLValue(addr, destTy);
487 return emitLoadOfLValue(destLV, op->getExprLoc());
488 }
489
490 case CK_LValueToRValueBitCast: {
491 LValue sourceLVal = cgf.emitLValue(op);
492 Address addr = sourceLVal.getAddress().withElementType(
493 builder, cgf.convertTypeForMem(destTy));
494 LValue destLV = cgf.makeAddrLValue(addr, destTy);
496 return emitLoadOfLValue(destLV, op->getExprLoc());
497 }
498
499 case CK_BitCast:
500 case CK_BaseToDerived:
501 case CK_DerivedToBase:
502 case CK_UncheckedDerivedToBase:
503 case CK_Dynamic:
504 case CK_ToUnion:
505 case CK_ArrayToPointerDecay:
506 case CK_FunctionToPointerDecay:
507 case CK_NullToPointer:
508 case CK_NullToMemberPointer:
509 case CK_BaseToDerivedMemberPointer:
510 case CK_DerivedToBaseMemberPointer:
511 case CK_MemberPointerToBoolean:
512 case CK_ReinterpretMemberPointer:
513 case CK_ConstructorConversion:
514 case CK_IntegralToPointer:
515 case CK_PointerToIntegral:
516 case CK_PointerToBoolean:
517 case CK_ToVoid:
518 case CK_VectorSplat:
519 case CK_IntegralCast:
520 case CK_BooleanToSignedIntegral:
521 case CK_IntegralToBoolean:
522 case CK_IntegralToFloating:
523 case CK_FloatingToIntegral:
524 case CK_FloatingToBoolean:
525 case CK_FloatingCast:
526 case CK_CPointerToObjCPointerCast:
527 case CK_BlockPointerToObjCPointerCast:
528 case CK_AnyPointerToBlockPointerCast:
529 case CK_ObjCObjectLValueCast:
530 case CK_FloatingComplexToReal:
531 case CK_FloatingComplexToBoolean:
532 case CK_IntegralComplexToReal:
533 case CK_IntegralComplexToBoolean:
534 case CK_ARCProduceObject:
535 case CK_ARCConsumeObject:
536 case CK_ARCReclaimReturnedObject:
537 case CK_ARCExtendBlockObject:
538 case CK_CopyAndAutoreleaseBlockObject:
539 case CK_BuiltinFnToFnPtr:
540 case CK_ZeroToOCLOpaqueType:
541 case CK_AddressSpaceConversion:
542 case CK_IntToOCLSampler:
543 case CK_FloatingToFixedPoint:
544 case CK_FixedPointToFloating:
545 case CK_FixedPointCast:
546 case CK_FixedPointToBoolean:
547 case CK_FixedPointToIntegral:
548 case CK_IntegralToFixedPoint:
549 case CK_MatrixCast:
550 case CK_HLSLVectorTruncation:
551 case CK_HLSLMatrixTruncation:
552 case CK_HLSLArrayRValue:
553 case CK_HLSLElementwiseCast:
554 case CK_HLSLAggregateSplatCast:
555 llvm_unreachable("invalid cast kind for complex value");
556
557 case CK_FloatingRealToComplex:
558 case CK_IntegralRealToComplex: {
560 return emitScalarToComplexCast(cgf.emitScalarExpr(op), op->getType(),
561 destTy, op->getExprLoc());
562 }
563
564 case CK_FloatingComplexCast:
565 case CK_FloatingComplexToIntegralComplex:
566 case CK_IntegralComplexCast:
567 case CK_IntegralComplexToFloatingComplex: {
569 return emitComplexToComplexCast(Visit(op), op->getType(), destTy,
570 op->getExprLoc());
571 }
572 }
573
574 llvm_unreachable("unknown cast resulting in complex value");
575}
576
577mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
578 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
579 mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Plus, promotionTy);
580 if (!promotionTy.isNull())
581 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
582 return result;
583}
584
585mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
586 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
587 mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
588 if (!promotionTy.isNull())
589 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
590 return result;
591}
592
593mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
594 cir::UnaryOpKind kind,
595 QualType promotionType) {
596 assert(kind == cir::UnaryOpKind::Plus ||
597 kind == cir::UnaryOpKind::Minus &&
598 "Invalid UnaryOp kind for ComplexType Plus or Minus");
599
600 mlir::Value op;
601 if (!promotionType.isNull())
602 op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
603 else
604 op = Visit(e->getSubExpr());
605 return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op);
606}
607
608mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
609 mlir::Value op = Visit(e->getSubExpr());
610 return builder.createNot(op);
611}
612
613mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
616
617 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
618 mlir::isa<cir::ComplexType>(op.rhs.getType()))
619 return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs);
620
621 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
622 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
623 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
624 mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs);
625 return builder.createComplexCreate(op.loc, newReal, imag);
626 }
627
628 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
629 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
630 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
631 mlir::Value newReal = builder.createAdd(op.loc, op.lhs, real);
632 return builder.createComplexCreate(op.loc, newReal, imag);
633}
634
635mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
638
639 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
640 mlir::isa<cir::ComplexType>(op.rhs.getType()))
641 return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs);
642
643 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
644 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
645 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
646 mlir::Value newReal = builder.createSub(op.loc, real, op.rhs);
647 return builder.createComplexCreate(op.loc, newReal, imag);
648 }
649
650 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
651 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
652 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
653 mlir::Value newReal = builder.createSub(op.loc, op.lhs, real);
654 return builder.createComplexCreate(op.loc, newReal, imag);
655}
656
657static cir::ComplexRangeKind
659 switch (range) {
661 return cir::ComplexRangeKind::Full;
663 return cir::ComplexRangeKind::Improved;
665 return cir::ComplexRangeKind::Promoted;
667 return cir::ComplexRangeKind::Basic;
669 // The default value for ComplexRangeKind is Full if no option is selected
670 return cir::ComplexRangeKind::Full;
671 }
672}
673
674mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
677
678 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
679 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
680 cir::ComplexRangeKind rangeKind =
681 getComplexRangeAttr(op.fpFeatures.getComplexRange());
682 return cir::ComplexMulOp::create(builder, op.loc, op.lhs, op.rhs,
683 rangeKind);
684 }
685
686 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
687 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
688 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
689 mlir::Value newReal = builder.createMul(op.loc, real, op.rhs);
690 mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs);
691 return builder.createComplexCreate(op.loc, newReal, newImag);
692 }
693
694 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
695 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
696 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
697 mlir::Value newReal = builder.createMul(op.loc, op.lhs, real);
698 mlir::Value newImag = builder.createMul(op.loc, op.lhs, imag);
699 return builder.createComplexCreate(op.loc, newReal, newImag);
700}
701
702mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) {
705
706 // Handle division between two complex values. In the case of complex integer
707 // types mixed with scalar integers, the scalar integer type will always be
708 // promoted to a complex integer value with a zero imaginary component when
709 // the AST is formed.
710 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
711 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
712 cir::ComplexRangeKind rangeKind =
713 getComplexRangeAttr(op.fpFeatures.getComplexRange());
714 return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs,
715 rangeKind);
716 }
717
718 // The C99 standard (G.5.1) defines division of a complex value by a real
719 // value in the following simplified form.
720 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
721 assert(mlir::cast<cir::ComplexType>(op.lhs.getType()).getElementType() ==
722 op.rhs.getType());
723 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
724 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
725 mlir::Value newReal = builder.createFDiv(op.loc, real, op.rhs);
726 mlir::Value newImag = builder.createFDiv(op.loc, imag, op.rhs);
727 return builder.createComplexCreate(op.loc, newReal, newImag);
728 }
729
730 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
731 cir::ConstantOp nullValue = builder.getNullValue(op.lhs.getType(), op.loc);
732 mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue);
733 cir::ComplexRangeKind rangeKind =
734 getComplexRangeAttr(op.fpFeatures.getComplexRange());
735 return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind);
736}
737
738mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result,
739 QualType unPromotionType) {
740 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
741 "integral complex will never be promoted");
742 return builder.createCast(cir::CastKind::float_complex, result,
743 convertType(unPromotionType));
744}
745
746mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result,
747 QualType promotionType) {
748 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
749 "integral complex will never be promoted");
750 return builder.createCast(cir::CastKind::float_complex, result,
751 convertType(promotionType));
752}
753
754mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
755 QualType promotionTy) {
756 e = e->IgnoreParens();
757 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
758 switch (bo->getOpcode()) {
759#define HANDLE_BINOP(OP) \
760 case BO_##OP: \
761 return emitBin##OP(emitBinOps(bo, promotionTy));
762 HANDLE_BINOP(Add)
763 HANDLE_BINOP(Sub)
764 HANDLE_BINOP(Mul)
765 HANDLE_BINOP(Div)
766#undef HANDLE_BINOP
767 default:
768 break;
769 }
770 } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) {
771 switch (unaryOp->getOpcode()) {
772 case UO_Minus:
773 case UO_Plus: {
774 auto kind = unaryOp->getOpcode() == UO_Plus ? cir::UnaryOpKind::Plus
775 : cir::UnaryOpKind::Minus;
776 return VisitPlusMinus(unaryOp, kind, promotionTy);
777 }
778 default:
779 break;
780 }
781 }
782
783 mlir::Value result = Visit(const_cast<Expr *>(e));
784 if (!promotionTy.isNull())
785 return cgf.emitPromotedValue(result, promotionTy);
786
787 return result;
788}
789
791 QualType promotionType) {
792 return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
793}
794
795mlir::Value
796ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
797 QualType promotionTy) {
798 if (e->getType()->isAnyComplexType()) {
799 if (!promotionTy.isNull())
800 return cgf.emitPromotedComplexExpr(e, promotionTy);
801 return Visit(const_cast<Expr *>(e));
802 }
803
804 if (!promotionTy.isNull()) {
805 QualType complexElementTy =
806 promotionTy->castAs<ComplexType>()->getElementType();
807 return cgf.emitPromotedScalarExpr(e, complexElementTy);
808 }
809 return cgf.emitScalarExpr(e);
810}
811
812ComplexExprEmitter::BinOpInfo
813ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
814 BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};
815 binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);
816 binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);
817 binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;
818 binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
819 return binOpInfo;
820}
821
822LValue ComplexExprEmitter::emitCompoundAssignLValue(
823 const CompoundAssignOperator *e,
824 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) {
825 QualType lhsTy = e->getLHS()->getType();
826 QualType rhsTy = e->getRHS()->getType();
827 SourceLocation exprLoc = e->getExprLoc();
828 mlir::Location loc = cgf.getLoc(exprLoc);
829
830 if (lhsTy->getAs<AtomicType>()) {
831 cgf.cgm.errorNYI("emitCompoundAssignLValue AtmoicType");
832 return {};
833 }
834
835 BinOpInfo opInfo{loc};
836 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
837
839
840 // Load the RHS and LHS operands.
841 // __block variables need to have the rhs evaluated first, plus this should
842 // improve codegen a little.
843 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
844 opInfo.ty = promotionTypeCR.isNull() ? e->getComputationResultType()
845 : promotionTypeCR;
846
847 QualType complexElementTy =
848 opInfo.ty->castAs<ComplexType>()->getElementType();
849 QualType promotionTypeRHS = getPromotionType(rhsTy);
850
851 // The RHS should have been converted to the computation type.
852 if (e->getRHS()->getType()->isRealFloatingType()) {
853 if (!promotionTypeRHS.isNull()) {
854 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
855 } else {
856 assert(cgf.getContext().hasSameUnqualifiedType(complexElementTy, rhsTy));
857 opInfo.rhs = cgf.emitScalarExpr(e->getRHS());
858 }
859 } else {
860 if (!promotionTypeRHS.isNull()) {
861 opInfo.rhs = cgf.emitPromotedComplexExpr(e->getRHS(), promotionTypeRHS);
862 } else {
863 assert(cgf.getContext().hasSameUnqualifiedType(opInfo.ty, rhsTy));
864 opInfo.rhs = Visit(e->getRHS());
865 }
866 }
867
868 LValue lhs = cgf.emitLValue(e->getLHS());
869
870 // Load from the l-value and convert it.
871 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
872 if (lhsTy->isAnyComplexType()) {
873 mlir::Value lhsValue = emitLoadOfLValue(lhs, exprLoc);
874 QualType destTy = promotionTypeLHS.isNull() ? opInfo.ty : promotionTypeLHS;
875 opInfo.lhs = emitComplexToComplexCast(lhsValue, lhsTy, destTy, exprLoc);
876 } else {
877 mlir::Value lhsVal = cgf.emitLoadOfScalar(lhs, exprLoc);
878 // For floating point real operands we can directly pass the scalar form
879 // to the binary operator emission and potentially get more efficient code.
880 if (lhsTy->isRealFloatingType()) {
881 QualType promotedComplexElementTy;
882 if (!promotionTypeLHS.isNull()) {
883 promotedComplexElementTy =
884 cast<ComplexType>(promotionTypeLHS)->getElementType();
885 if (!cgf.getContext().hasSameUnqualifiedType(promotedComplexElementTy,
886 promotionTypeLHS))
887 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy,
888 promotedComplexElementTy, exprLoc);
889 } else {
890 if (!cgf.getContext().hasSameUnqualifiedType(complexElementTy, lhsTy))
891 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy, complexElementTy,
892 exprLoc);
893 }
894 opInfo.lhs = lhsVal;
895 } else {
896 opInfo.lhs = emitScalarToComplexCast(lhsVal, lhsTy, opInfo.ty, exprLoc);
897 }
898 }
899
900 // Expand the binary operator.
901 mlir::Value result = (this->*func)(opInfo);
902
903 // Truncate the result and store it into the LHS lvalue.
904 if (lhsTy->isAnyComplexType()) {
905 mlir::Value resultValue =
906 emitComplexToComplexCast(result, opInfo.ty, lhsTy, exprLoc);
907 emitStoreOfComplex(loc, resultValue, lhs, /*isInit*/ false);
908 value = RValue::getComplex(resultValue);
909 } else {
910 mlir::Value resultValue =
911 cgf.emitComplexToScalarConversion(result, opInfo.ty, lhsTy, exprLoc);
912 cgf.emitStoreOfScalar(resultValue, lhs, /*isInit*/ false);
913 value = RValue::get(resultValue);
914 }
915
916 return lhs;
917}
918
919mlir::Value ComplexExprEmitter::emitCompoundAssign(
920 const CompoundAssignOperator *e,
921 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)) {
922 RValue val;
923 LValue lv = emitCompoundAssignLValue(e, func, val);
924
925 // The result of an assignment in C is the assigned r-value.
926 if (!cgf.getLangOpts().CPlusPlus)
927 return val.getComplexValue();
928
929 // If the lvalue is non-volatile, return the computed value of the assignment.
930 if (!lv.isVolatileQualified())
931 return val.getComplexValue();
932
933 return emitLoadOfLValue(lv, e->getExprLoc());
934}
935
936LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
937 mlir::Value &value) {
938 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
939 e->getRHS()->getType()) &&
940 "Invalid assignment");
941
942 // Emit the RHS. __block variables need the RHS evaluated first.
943 value = Visit(e->getRHS());
944
945 // Compute the address to store into.
946 LValue lhs = cgf.emitLValue(e->getLHS());
947
948 // Store the result value into the LHS lvalue.
949 emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs,
950 /*isInit*/ false);
951 return lhs;
952}
953
954mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
955 mlir::Value value;
956 LValue lv = emitBinAssignLValue(e, value);
957
958 // The result of an assignment in C is the assigned r-value.
959 if (!cgf.getLangOpts().CPlusPlus)
960 return value;
961
962 // If the lvalue is non-volatile, return the computed value of the
963 // assignment.
964 if (!lv.isVolatile())
965 return value;
966
967 return emitLoadOfLValue(lv, e->getExprLoc());
968}
969
970mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
971 cgf.emitIgnoredExpr(e->getLHS());
972 return Visit(e->getRHS());
973}
974
975mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(
976 const AbstractConditionalOperator *e) {
977 mlir::Location loc = cgf.getLoc(e->getSourceRange());
978
979 // Bind the common expression if necessary.
980 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
981
982 CIRGenFunction::ConditionalEvaluation eval(cgf);
983
984 Expr *cond = e->getCond()->IgnoreParens();
985 mlir::Value condValue = cgf.evaluateExprAsBool(cond);
986
987 return cir::TernaryOp::create(
988 builder, loc, condValue,
989 /*thenBuilder=*/
990 [&](mlir::OpBuilder &b, mlir::Location loc) {
991 eval.beginEvaluation();
992 mlir::Value trueValue = Visit(e->getTrueExpr());
993 cir::YieldOp::create(b, loc, trueValue);
994 eval.endEvaluation();
995 },
996 /*elseBuilder=*/
997 [&](mlir::OpBuilder &b, mlir::Location loc) {
998 eval.beginEvaluation();
999 mlir::Value falseValue = Visit(e->getFalseExpr());
1000 cir::YieldOp::create(b, loc, falseValue);
1001 eval.endEvaluation();
1002 })
1003 .getResult();
1004}
1005
1006mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
1007 return Visit(e->getChosenSubExpr());
1008}
1009
1010mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
1011 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1012 if (e->getNumInits() == 2) {
1013 mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
1014 mlir::Value imag = cgf.emitScalarExpr(e->getInit(1));
1015 return builder.createComplexCreate(loc, real, imag);
1016 }
1017
1018 if (e->getNumInits() == 1)
1019 return Visit(e->getInit(0));
1020
1021 assert(e->getNumInits() == 0 && "Unexpected number of inits");
1022 mlir::Type complexTy = cgf.convertType(e->getType());
1023 return builder.getNullValue(complexTy, loc);
1024}
1025
1026mlir::Value ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *e) {
1027 return cgf.emitVAArg(e);
1028}
1029
1030//===----------------------------------------------------------------------===//
1031// Entry Point into this File
1032//===----------------------------------------------------------------------===//
1033
1034/// EmitComplexExpr - Emit the computation of the specified expression of
1035/// complex type, ignoring the result.
1037 assert(e && getComplexType(e->getType()) &&
1038 "Invalid complex expression to emit");
1039
1040 return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));
1041}
1042
1044 bool isInit) {
1045 assert(e && getComplexType(e->getType()) &&
1046 "Invalid complex expression to emit");
1047 ComplexExprEmitter emitter(*this);
1048 mlir::Value value = emitter.Visit(const_cast<Expr *>(e));
1049 emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit);
1050}
1051
1052/// EmitStoreOfComplex - Store a complex number into the specified l-value.
1053void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
1054 LValue dest, bool isInit) {
1055 ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
1056}
1057
1059 return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);
1060}
1061
1063 assert(e->getOpcode() == BO_Assign && "Expected assign op");
1064
1065 mlir::Value value; // ignored
1066 LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
1067 if (getLangOpts().OpenMP)
1068 cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
1069
1070 return lvalue;
1071}
1072
1074 mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &);
1075
1077 switch (op) {
1078 case BO_MulAssign:
1079 return &ComplexExprEmitter::emitBinMul;
1080 case BO_DivAssign:
1081 return &ComplexExprEmitter::emitBinDiv;
1082 case BO_SubAssign:
1083 return &ComplexExprEmitter::emitBinSub;
1084 case BO_AddAssign:
1085 return &ComplexExprEmitter::emitBinAdd;
1086 default:
1087 llvm_unreachable("unexpected complex compound assignment");
1088 }
1089}
1090
1092 const CompoundAssignOperator *e) {
1094 RValue val;
1095 return ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, val);
1096}
1097
1099 LValue lv,
1100 cir::UnaryOpKind op,
1101 bool isPre) {
1102 assert(op == cir::UnaryOpKind::Inc ||
1103 op == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind for ComplexType");
1104
1105 mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc());
1106 mlir::Location loc = getLoc(e->getExprLoc());
1107 mlir::Value incVal = builder.createUnaryOp(loc, op, inVal);
1108
1109 // Store the updated result through the lvalue.
1110 emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false);
1111
1112 if (getLangOpts().OpenMP)
1113 cgm.errorNYI(loc, "emitComplexPrePostIncDec OpenMP");
1114
1115 // If this is a postinc, return the value read from memory, otherwise use the
1116 // updated value.
1117 return isPre ? incVal : inVal;
1118}
1119
1121 const CompoundAssignOperator *e, mlir::Value &result) {
1122 // Key Instructions: Don't need to create an atom group here; one will already
1123 // be active through scalar handling code.
1125 RValue value;
1126 LValue ret = ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, value);
1127 result = value.getValue();
1128 return ret;
1129}
#define HANDLEBINOP(OP)
static CompoundFunc getComplexOp(BinaryOperatorKind op)
static const ComplexType * getComplexType(QualType type)
Return the complex type that we are meant to emit.
mlir::Value(ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &) CompoundFunc
static cir::ComplexRangeKind getComplexRangeAttr(LangOptions::ComplexRangeKind range)
#define HANDLE_BINOP(OP)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNot(mlir::Value value)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::Saturated)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind, mlir::Value operand)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
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:4531
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4537
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4543
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4038
Expr * getLHS() const
Definition Expr.h:4088
SourceLocation getExprLoc() const
Definition Expr.h:4079
Expr * getRHS() const
Definition Expr.h:4090
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:4251
Opcode getOpcode() const
Definition Expr.h:4083
bool isValid() const
Definition Address.h:74
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const
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)
const clang::LangOptions & getLangOpts() const
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,...
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
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...
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType)
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind op, bool isPre)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
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)
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
clang::ASTContext & getContext() const
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getComplex(mlir::Value v)
Definition CIRGenValue.h:91
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
mlir::Value getComplexValue() const
Return the value of this complex value.
Definition CIRGenValue.h:63
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1105
A rewritten comparison expression that was originally written using operator syntax.
Definition ExprCXX.h:286
SourceLocation getExprLoc() const LLVM_READONLY
Definition ExprCXX.h:341
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1602
CastKind getCastKind() const
Definition Expr.h:3720
bool changesVolatileQualification() const
Return.
Definition Expr.h:3810
Expr * getSubExpr()
Definition Expr.h:3726
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4884
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3276
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4300
QualType getComputationLHSType() const
Definition Expr.h:4334
QualType getComputationResultType() const
Definition Expr.h:4337
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3085
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
QualType getType() const
Definition Expr.h:144
const Expr * getSubExpr() const
Definition Expr.h:1062
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6462
const Expr * getSubExpr() const
Definition Expr.h:1743
unsigned getNumInits() const
Definition Expr.h:5329
const Expr * getInit(unsigned Init) const
Definition Expr.h:5353
ComplexRangeKind
Controls the various implementations for complex multiplication and.
@ CX_Full
Implementation of complex division and multiplication using a call to runtime library functions(gener...
@ CX_Basic
Implementation of complex division and multiplication using algebraic formulas at source precision.
@ CX_Promoted
Implementation of complex division using algebraic formulas at higher precision.
@ CX_None
No range rule is enabled.
@ CX_Improved
Implementation of complex division offering an improved handling for overflow in intermediate calcula...
Expr * getBase() const
Definition Expr.h:3441
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:1208
const Expr * getSubExpr() const
Definition Expr.h:2199
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:6842
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
bool UseExcessPrecision(const ASTContext &Ctx)
Definition Type.cpp:1613
Encodes a location in the source.
CompoundStmt * getSubStmt()
Definition Expr.h:4612
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:338
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8935
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9178
bool isReferenceType() const
Definition TypeBase.h:8553
bool isAnyComplexType() const
Definition TypeBase.h:8664
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2321
bool isFloatingType() const
Definition Type.cpp:2305
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9111
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
SourceLocation getExprLoc() const
Definition Expr.h:2368
Expr * getSubExpr() const
Definition Expr.h:2285
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool cgFPOptionsRAII()
static bool fastMathFlags()