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 s->dump(llvm::errs(), cgf.getContext());
65 llvm_unreachable("Stmt can't have complex result type!");
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 return cgf.emitCoawaitExpr(*s).getComplexValue();
90 }
91 mlir::Value VisitCoyieldExpr(CoyieldExpr *s) {
92 cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr");
93 return {};
94 }
95 mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
96 cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait");
97 return {};
98 }
99
100 mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,
101 Expr *e) {
102 assert(constant && "not a constant");
103 if (constant.isReference())
104 return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),
105 e->getExprLoc());
106
107 mlir::TypedAttr valueAttr = constant.getValue();
108 return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);
109 }
110
111 // l-values.
112 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
113 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
114 return emitConstant(constant, e);
115 return emitLoadOfLValue(e);
116 }
117 mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) {
118 cgf.cgm.errorNYI(e->getExprLoc(),
119 "ComplexExprEmitter VisitObjCIvarRefExpr");
120 return {};
121 }
122 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
123 cgf.cgm.errorNYI(e->getExprLoc(),
124 "ComplexExprEmitter VisitObjCMessageExpr");
125 return {};
126 }
127 mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); }
128 mlir::Value VisitMemberExpr(MemberExpr *me) {
129 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
130 cgf.emitIgnoredExpr(me->getBase());
131 return emitConstant(constant, me);
132 }
133 return emitLoadOfLValue(me);
134 }
135 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
136 if (e->isGLValue())
137 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
138 e->getExprLoc());
139 return cgf.getOrCreateOpaqueRValueMapping(e).getComplexValue();
140 }
141
142 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
143 cgf.cgm.errorNYI(e->getExprLoc(),
144 "ComplexExprEmitter VisitPseudoObjectExpr");
145 return {};
146 }
147
148 mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
149 mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e) {
150 // Unlike for scalars, we don't have to worry about function->ptr demotion
151 // here.
153 return emitLoadOfLValue(e);
154 return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
155 }
156 mlir::Value VisitCastExpr(CastExpr *e) {
157 if (const auto *ece = dyn_cast<ExplicitCastExpr>(e))
158 cgf.cgm.emitExplicitCastExprType(ece);
160 return emitLoadOfLValue(e);
161 return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
162 }
163 mlir::Value VisitCallExpr(const CallExpr *e);
164 mlir::Value VisitStmtExpr(const StmtExpr *e);
165
166 // Operators.
167 mlir::Value VisitPrePostIncDec(const UnaryOperator *e) {
168 LValue lv = cgf.emitLValue(e->getSubExpr());
169 return cgf.emitComplexPrePostIncDec(e, lv);
170 }
171 mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
172 return VisitPrePostIncDec(e);
173 }
174 mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
175 return VisitPrePostIncDec(e);
176 }
177 mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
178 return VisitPrePostIncDec(e);
179 }
180 mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
181 return VisitPrePostIncDec(e);
182 }
183 mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }
184
185 mlir::Value VisitUnaryPlus(const UnaryOperator *e);
186 mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType);
187 mlir::Value VisitUnaryMinus(const UnaryOperator *e);
188 mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType);
189 mlir::Value VisitUnaryNot(const UnaryOperator *e);
190 // LNot,Real,Imag never return complex.
191 mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
192 return Visit(e->getSubExpr());
193 }
194 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
195 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
196 return Visit(dae->getExpr());
197 }
198 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
199 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
200 return Visit(die->getExpr());
201 }
202 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) {
203 CIRGenFunction::FullExprCleanupScope scope(cgf, e->getSubExpr());
204 mlir::Value complexVal = Visit(e->getSubExpr());
205 // Defend against dominance problems caused by jumps out of expression
206 // evaluation through the shared cleanup block.
207 scope.exit({&complexVal});
208 return complexVal;
209 }
210 mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
211 mlir::Location loc = cgf.getLoc(e->getExprLoc());
212 mlir::Type complexTy = cgf.convertType(e->getType());
213 return builder.getNullValue(complexTy, loc);
214 }
215 mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
216 mlir::Location loc = cgf.getLoc(e->getExprLoc());
217 mlir::Type complexTy = cgf.convertType(e->getType());
218 return builder.getNullValue(complexTy, loc);
219 }
220
221 struct BinOpInfo {
222 mlir::Location loc;
223 mlir::Value lhs{};
224 mlir::Value rhs{};
225 QualType ty{}; // Computation Type.
226 FPOptions fpFeatures{};
227 };
228
229 BinOpInfo emitBinOps(const BinaryOperator *e,
230 QualType promotionTy = QualType());
231
232 mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
233 mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
234 LValue emitCompoundAssignLValue(
235 const CompoundAssignOperator *e,
236 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
237 RValue &value);
238 mlir::Value emitCompoundAssign(
239 const CompoundAssignOperator *e,
240 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
241
242 mlir::Value emitBinAdd(const BinOpInfo &op);
243 mlir::Value emitBinSub(const BinOpInfo &op);
244 mlir::Value emitBinMul(const BinOpInfo &op);
245 mlir::Value emitBinDiv(const BinOpInfo &op);
246
247 QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
248 if (auto *complexTy = ty->getAs<ComplexType>()) {
249 QualType elementTy = complexTy->getElementType();
250 if (elementTy.UseExcessPrecision(cgf.getContext()))
251 return cgf.getContext().getComplexType(cgf.getContext().FloatTy);
252 }
253
254 if (ty.UseExcessPrecision(cgf.getContext()))
255 return cgf.getContext().FloatTy;
256 return QualType();
257 }
258
259#define HANDLEBINOP(OP) \
260 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
261 QualType promotionTy = getPromotionType( \
262 e->getType(), e->getOpcode() == BinaryOperatorKind::BO_Div); \
263 mlir::Value result = emitBin##OP(emitBinOps(e, promotionTy)); \
264 if (!promotionTy.isNull()) \
265 result = cgf.emitUnPromotedValue(result, e->getType()); \
266 return result; \
267 }
268
269 HANDLEBINOP(Add)
270 HANDLEBINOP(Sub)
271 HANDLEBINOP(Mul)
272 HANDLEBINOP(Div)
273#undef HANDLEBINOP
274
275 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
276 cgf.cgm.errorNYI(e->getExprLoc(),
277 "ComplexExprEmitter VisitCXXRewrittenBinaryOperator");
278 return {};
279 }
280
281 // Compound assignments.
282 mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
283 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
284 }
285 mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
286 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
287 }
288 mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) {
289 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul);
290 }
291 mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) {
292 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv);
293 }
294
295 // GCC rejects rem/and/or/xor for integer complex.
296 // Logical and/or always return int, never complex.
297
298 // No comparisons produce a complex result.
299
300 LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
301 mlir::Value VisitBinAssign(const BinaryOperator *e);
302 mlir::Value VisitBinComma(const BinaryOperator *e);
303
304 mlir::Value
305 VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
306 mlir::Value VisitChooseExpr(ChooseExpr *e);
307
308 mlir::Value VisitInitListExpr(InitListExpr *e);
309
310 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
311 return emitLoadOfLValue(e);
312 }
313
314 mlir::Value VisitVAArgExpr(VAArgExpr *e);
315
316 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
317 return cgf.emitAtomicExpr(e).getComplexValue();
318 }
319
320 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
321 return Visit(e->getSelectedExpr());
322 }
323};
324} // namespace
325
326//===----------------------------------------------------------------------===//
327// Utilities
328//===----------------------------------------------------------------------===//
329
330/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
331/// load the real and imaginary pieces, returning them as Real/Imag.
332mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
333 SourceLocation loc) {
334 assert(lv.isSimple() && "non-simple complex l-value?");
335 if (lv.getType()->isAtomicType())
336 return cgf.emitAtomicLoad(lv, loc).getComplexValue();
337
338 const Address srcAddr = lv.getAddress();
339 return builder.createLoad(cgf.getLoc(loc), srcAddr, lv.isVolatileQualified());
340}
341
342/// EmitStoreOfComplex - Store the specified real/imag parts into the
343/// specified value pointer.
344void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
345 LValue lv, bool isInit) {
346 if (lv.getType()->isAtomicType() ||
347 (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
348 return cgf.emitAtomicStore(RValue::getComplex(val), lv, isInit);
349 }
350
351 const Address destAddr = lv.getAddress();
352 builder.createStore(loc, val, destAddr, lv.isVolatileQualified());
353}
354
355//===----------------------------------------------------------------------===//
356// Visitor Methods
357//===----------------------------------------------------------------------===//
358
359mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) {
360 cgf.cgm.errorUnsupported(e, "complex expression");
361 mlir::Type complexTy = cgf.convertType(e->getType());
362 mlir::Location loc = cgf.getLoc(e->getExprLoc());
363 return builder.getConstant(loc, cir::PoisonAttr::get(complexTy));
364}
365
366mlir::Value
367ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
368 auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
369 mlir::Type elementTy = ty.getElementType();
370 mlir::Location loc = cgf.getLoc(il->getExprLoc());
371
372 mlir::TypedAttr realValueAttr;
373 mlir::TypedAttr imagValueAttr;
374
375 if (mlir::isa<cir::IntType>(elementTy)) {
376 llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
377 realValueAttr = cir::IntAttr::get(elementTy, 0);
378 imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
379 } else {
380 assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
381 "Expected complex element type to be floating-point");
382
383 llvm::APFloat imagValue =
384 cast<FloatingLiteral>(il->getSubExpr())->getValue();
385 realValueAttr = cir::FPAttr::get(
386 elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
387 imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
388 }
389
390 auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
391 return cir::ConstantOp::create(builder, loc, complexAttr);
392}
393
394mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
396 return emitLoadOfLValue(e);
397 return cgf.emitCallExpr(e).getComplexValue();
398}
399
400mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
401 CIRGenFunction::StmtExprEvaluation eval(cgf);
402 Address retAlloca =
403 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
404 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
405 assert(retAlloca.isValid() && "Expected complex return value");
406 return emitLoadOfLValue(cgf.makeAddrLValue(retAlloca, e->getType()),
407 e->getExprLoc());
408}
409
410mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
411 QualType srcType,
412 QualType destType,
413 SourceLocation loc) {
414 if (srcType == destType)
415 return val;
416
417 // Get the src/dest element type.
418 QualType srcElemTy = srcType.getAtomicUnqualifiedType()
419 ->castAs<ComplexType>()
420 ->getElementType();
421 QualType destElemTy = destType.getAtomicUnqualifiedType()
422 ->castAs<ComplexType>()
423 ->getElementType();
424
425 cir::CastKind castOpKind;
426 if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
427 castOpKind = cir::CastKind::float_complex;
428 else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
429 castOpKind = cir::CastKind::float_complex_to_int_complex;
430 else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
431 castOpKind = cir::CastKind::int_complex_to_float_complex;
432 else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
433 castOpKind = cir::CastKind::int_complex;
434 else
435 llvm_unreachable("unexpected src type or dest type");
436
437 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
438 cgf.convertType(destType));
439}
440
441mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
442 QualType srcType,
443 QualType destType,
444 SourceLocation loc) {
445 cir::CastKind castOpKind;
446 if (srcType->isFloatingType())
447 castOpKind = cir::CastKind::float_to_complex;
448 else if (srcType->isIntegerType())
449 castOpKind = cir::CastKind::int_to_complex;
450 else
451 llvm_unreachable("unexpected src type");
452
453 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
454 cgf.convertType(destType));
455}
456
457mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
458 QualType destTy) {
459 destTy = destTy.getAtomicUnqualifiedType();
460 switch (ck) {
461 case CK_Dependent:
462 llvm_unreachable("dependent type must be resolved before the CIR codegen");
463
464 // Atomic to non-atomic casts may be more than a no-op for some platforms
465 // and for some types.
466 case CK_NonAtomicToAtomic:
467 case CK_AtomicToNonAtomic:
468 case CK_NoOp:
469 case CK_LValueToRValue:
470 case CK_UserDefinedConversion:
471 return Visit(op);
472
473 case CK_LValueBitCast: {
474 LValue origLV = cgf.emitLValue(op);
475 Address addr =
476 origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
477 LValue destLV = cgf.makeAddrLValue(addr, destTy);
478 return emitLoadOfLValue(destLV, op->getExprLoc());
479 }
480
481 case CK_LValueToRValueBitCast: {
482 LValue sourceLVal = cgf.emitLValue(op);
483 Address addr = sourceLVal.getAddress().withElementType(
484 builder, cgf.convertTypeForMem(destTy));
485 LValue destLV = cgf.makeAddrLValue(addr, destTy);
487 return emitLoadOfLValue(destLV, op->getExprLoc());
488 }
489
490 case CK_BitCast:
491 case CK_BaseToDerived:
492 case CK_DerivedToBase:
493 case CK_UncheckedDerivedToBase:
494 case CK_Dynamic:
495 case CK_ToUnion:
496 case CK_ArrayToPointerDecay:
497 case CK_FunctionToPointerDecay:
498 case CK_NullToPointer:
499 case CK_NullToMemberPointer:
500 case CK_BaseToDerivedMemberPointer:
501 case CK_DerivedToBaseMemberPointer:
502 case CK_MemberPointerToBoolean:
503 case CK_ReinterpretMemberPointer:
504 case CK_ConstructorConversion:
505 case CK_IntegralToPointer:
506 case CK_PointerToIntegral:
507 case CK_PointerToBoolean:
508 case CK_ToVoid:
509 case CK_VectorSplat:
510 case CK_IntegralCast:
511 case CK_BooleanToSignedIntegral:
512 case CK_IntegralToBoolean:
513 case CK_IntegralToFloating:
514 case CK_FloatingToIntegral:
515 case CK_FloatingToBoolean:
516 case CK_FloatingCast:
517 case CK_CPointerToObjCPointerCast:
518 case CK_BlockPointerToObjCPointerCast:
519 case CK_AnyPointerToBlockPointerCast:
520 case CK_ObjCObjectLValueCast:
521 case CK_FloatingComplexToReal:
522 case CK_FloatingComplexToBoolean:
523 case CK_IntegralComplexToReal:
524 case CK_IntegralComplexToBoolean:
525 case CK_ARCProduceObject:
526 case CK_ARCConsumeObject:
527 case CK_ARCReclaimReturnedObject:
528 case CK_ARCExtendBlockObject:
529 case CK_CopyAndAutoreleaseBlockObject:
530 case CK_BuiltinFnToFnPtr:
531 case CK_ZeroToOCLOpaqueType:
532 case CK_AddressSpaceConversion:
533 case CK_IntToOCLSampler:
534 case CK_FloatingToFixedPoint:
535 case CK_FixedPointToFloating:
536 case CK_FixedPointCast:
537 case CK_FixedPointToBoolean:
538 case CK_FixedPointToIntegral:
539 case CK_IntegralToFixedPoint:
540 case CK_MatrixCast:
541 case CK_HLSLVectorTruncation:
542 case CK_HLSLMatrixTruncation:
543 case CK_HLSLArrayRValue:
544 case CK_HLSLElementwiseCast:
545 case CK_HLSLAggregateSplatCast:
546 llvm_unreachable("invalid cast kind for complex value");
547
548 case CK_FloatingRealToComplex:
549 case CK_IntegralRealToComplex: {
550 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op);
551 return emitScalarToComplexCast(cgf.emitScalarExpr(op), op->getType(),
552 destTy, op->getExprLoc());
553 }
554
555 case CK_FloatingComplexCast:
556 case CK_FloatingComplexToIntegralComplex:
557 case CK_IntegralComplexCast:
558 case CK_IntegralComplexToFloatingComplex: {
559 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op);
560 return emitComplexToComplexCast(Visit(op), op->getType(), destTy,
561 op->getExprLoc());
562 }
563 }
564
565 llvm_unreachable("unknown cast resulting in complex value");
566}
567
568mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
569 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
570 mlir::Value result = VisitUnaryPlus(e, promotionTy);
571 if (!promotionTy.isNull())
572 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
573 return result;
574}
575
576mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e,
577 QualType promotionType) {
578 if (!promotionType.isNull())
579 return cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
580 return Visit(e->getSubExpr());
581}
582
583mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
584 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
585 mlir::Value result = VisitUnaryMinus(e, promotionTy);
586 if (!promotionTy.isNull())
587 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
588 return result;
589}
590
591mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e,
592 QualType promotionType) {
593 mlir::Value op;
594 if (!promotionType.isNull())
595 op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
596 else
597 op = Visit(e->getSubExpr());
598
599 // Negate each component of the complex value.
600 mlir::Location loc = cgf.getLoc(e->getExprLoc());
601 mlir::Value real = builder.createComplexReal(loc, op);
602 mlir::Value imag = builder.createComplexImag(loc, op);
603
604 mlir::Value resultReal;
605 mlir::Value resultImag;
606 if (cir::isFPOrVectorOfFPType(real.getType())) {
607 resultReal = builder.createFNeg(loc, real);
608 resultImag = builder.createFNeg(loc, imag);
609 } else {
610 resultReal = builder.createMinus(loc, real);
611 resultImag = builder.createMinus(loc, imag);
612 }
613
614 return builder.createComplexCreate(loc, resultReal, resultImag);
615}
616
617mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
618 mlir::Value op = Visit(e->getSubExpr());
619 return builder.createComplexConj(cgf.getLoc(e->getExprLoc()), op);
620}
621
622mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
624 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op.fpFeatures);
625
626 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
627 mlir::isa<cir::ComplexType>(op.rhs.getType()))
628 return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs);
629
630 auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
631 return cir::isFPOrVectorOfFPType(a.getType())
632 ? builder.createFAdd(loc, a, b)
633 : builder.createAdd(loc, a, b);
634 };
635
636 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
637 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
638 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
639 mlir::Value newReal = createAdd(op.loc, real, op.rhs);
640 return builder.createComplexCreate(op.loc, newReal, imag);
641 }
642
643 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
644 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
645 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
646 mlir::Value newReal = createAdd(op.loc, op.lhs, real);
647 return builder.createComplexCreate(op.loc, newReal, imag);
648}
649
650mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
652 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op.fpFeatures);
653
654 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
655 mlir::isa<cir::ComplexType>(op.rhs.getType()))
656 return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs);
657
658 auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
659 return cir::isFPOrVectorOfFPType(a.getType())
660 ? builder.createFSub(loc, a, b)
661 : builder.createSub(loc, a, b);
662 };
663
664 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
665 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
666 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
667 mlir::Value newReal = createSub(op.loc, real, op.rhs);
668 return builder.createComplexCreate(op.loc, newReal, imag);
669 }
670
671 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
672 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
673 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
674 mlir::Value newReal = createSub(op.loc, op.lhs, real);
675 return builder.createComplexCreate(op.loc, newReal, imag);
676}
677
678static cir::ComplexRangeKind
680 switch (range) {
682 return cir::ComplexRangeKind::Full;
684 return cir::ComplexRangeKind::Improved;
686 return cir::ComplexRangeKind::Promoted;
688 return cir::ComplexRangeKind::Basic;
690 // The default value for ComplexRangeKind is Full if no option is selected
691 return cir::ComplexRangeKind::Full;
692 }
693}
694
695mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
697 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op.fpFeatures);
698
699 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
700 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
701 cir::ComplexRangeKind rangeKind =
702 getComplexRangeAttr(op.fpFeatures.getComplexRange());
703 return cir::ComplexMulOp::create(builder, op.loc, op.lhs, op.rhs,
704 rangeKind);
705 }
706
707 auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
708 return cir::isFPOrVectorOfFPType(a.getType())
709 ? builder.createFMul(loc, a, b)
710 : builder.createMul(loc, a, b);
711 };
712
713 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
714 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
715 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
716 mlir::Value newReal = createMul(op.loc, real, op.rhs);
717 mlir::Value newImag = createMul(op.loc, imag, op.rhs);
718 return builder.createComplexCreate(op.loc, newReal, newImag);
719 }
720
721 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
722 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
723 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
724 mlir::Value newReal = createMul(op.loc, op.lhs, real);
725 mlir::Value newImag = createMul(op.loc, op.lhs, imag);
726 return builder.createComplexCreate(op.loc, newReal, newImag);
727}
728
729mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) {
731 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, op.fpFeatures);
732
733 // Handle division between two complex values. In the case of complex integer
734 // types mixed with scalar integers, the scalar integer type will always be
735 // promoted to a complex integer value with a zero imaginary component when
736 // the AST is formed.
737 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
738 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
739 cir::ComplexRangeKind rangeKind =
740 getComplexRangeAttr(op.fpFeatures.getComplexRange());
741 return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs,
742 rangeKind);
743 }
744
745 // The C99 standard (G.5.1) defines division of a complex value by a real
746 // value in the following simplified form.
747 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
748 assert(mlir::cast<cir::ComplexType>(op.lhs.getType()).getElementType() ==
749 op.rhs.getType());
750 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
751 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
752 mlir::Value newReal = builder.createFDiv(op.loc, real, op.rhs);
753 mlir::Value newImag = builder.createFDiv(op.loc, imag, op.rhs);
754 return builder.createComplexCreate(op.loc, newReal, newImag);
755 }
756
757 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
758 cir::ConstantOp nullValue = builder.getNullValue(op.lhs.getType(), op.loc);
759 mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue);
760 cir::ComplexRangeKind rangeKind =
761 getComplexRangeAttr(op.fpFeatures.getComplexRange());
762 return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind);
763}
764
765mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result,
766 QualType unPromotionType) {
767 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
768 "integral complex will never be promoted");
769 return builder.createCast(cir::CastKind::float_complex, result,
770 convertType(unPromotionType));
771}
772
773mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result,
774 QualType promotionType) {
775 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
776 "integral complex will never be promoted");
777 return builder.createCast(cir::CastKind::float_complex, result,
778 convertType(promotionType));
779}
780
781mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
782 QualType promotionTy) {
783 e = e->IgnoreParens();
784 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
785 switch (bo->getOpcode()) {
786#define HANDLE_BINOP(OP) \
787 case BO_##OP: \
788 return emitBin##OP(emitBinOps(bo, promotionTy));
789 HANDLE_BINOP(Add)
790 HANDLE_BINOP(Sub)
791 HANDLE_BINOP(Mul)
792 HANDLE_BINOP(Div)
793#undef HANDLE_BINOP
794 default:
795 break;
796 }
797 } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) {
798 switch (unaryOp->getOpcode()) {
799 case UO_Plus:
800 return VisitUnaryPlus(unaryOp, promotionTy);
801 case UO_Minus:
802 return VisitUnaryMinus(unaryOp, promotionTy);
803 default:
804 break;
805 }
806 }
807
808 mlir::Value result = Visit(const_cast<Expr *>(e));
809 if (!promotionTy.isNull())
810 return cgf.emitPromotedValue(result, promotionTy);
811
812 return result;
813}
814
816 QualType promotionType) {
817 return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
818}
819
820mlir::Value
821ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
822 QualType promotionTy) {
823 if (e->getType()->isAnyComplexType()) {
824 if (!promotionTy.isNull())
825 return cgf.emitPromotedComplexExpr(e, promotionTy);
826 return Visit(const_cast<Expr *>(e));
827 }
828
829 if (!promotionTy.isNull()) {
830 QualType complexElementTy =
831 promotionTy->castAs<ComplexType>()->getElementType();
832 return cgf.emitPromotedScalarExpr(e, complexElementTy);
833 }
834 return cgf.emitScalarExpr(e);
835}
836
837ComplexExprEmitter::BinOpInfo
838ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
839 BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};
840 binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);
841 binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);
842 binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;
843 binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
844 return binOpInfo;
845}
846
847LValue ComplexExprEmitter::emitCompoundAssignLValue(
848 const CompoundAssignOperator *e,
849 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) {
850 QualType lhsTy = e->getLHS()->getType().getAtomicUnqualifiedType();
851 QualType rhsTy = e->getRHS()->getType();
852 SourceLocation exprLoc = e->getExprLoc();
853 mlir::Location loc = cgf.getLoc(exprLoc);
854
855 BinOpInfo opInfo{loc};
856 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
857
858 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, opInfo.fpFeatures);
859
860 // Load the RHS and LHS operands.
861 // __block variables need to have the rhs evaluated first, plus this should
862 // improve codegen a little.
863 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
864 opInfo.ty = promotionTypeCR.isNull() ? e->getComputationResultType()
865 : promotionTypeCR;
866
867 QualType complexElementTy =
868 opInfo.ty->castAs<ComplexType>()->getElementType();
869 QualType promotionTypeRHS = getPromotionType(rhsTy);
870
871 // The RHS should have been converted to the computation type.
872 if (e->getRHS()->getType()->isRealFloatingType()) {
873 if (!promotionTypeRHS.isNull()) {
874 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
875 } else {
876 assert(cgf.getContext().hasSameUnqualifiedType(complexElementTy, rhsTy));
877 opInfo.rhs = cgf.emitScalarExpr(e->getRHS());
878 }
879 } else {
880 if (!promotionTypeRHS.isNull()) {
881 opInfo.rhs = cgf.emitPromotedComplexExpr(e->getRHS(), promotionTypeRHS);
882 } else {
883 assert(cgf.getContext().hasSameUnqualifiedType(opInfo.ty, rhsTy));
884 opInfo.rhs = Visit(e->getRHS());
885 }
886 }
887
888 LValue lhs = cgf.emitLValue(e->getLHS());
889
890 // Load from the l-value and convert it.
891 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
892 if (lhsTy->isAnyComplexType()) {
893 mlir::Value lhsValue = emitLoadOfLValue(lhs, exprLoc);
894 QualType destTy = promotionTypeLHS.isNull() ? opInfo.ty : promotionTypeLHS;
895 opInfo.lhs = emitComplexToComplexCast(lhsValue, lhsTy, destTy, exprLoc);
896 } else {
897 mlir::Value lhsVal = cgf.emitLoadOfScalar(lhs, exprLoc);
898 // For floating point real operands we can directly pass the scalar form
899 // to the binary operator emission and potentially get more efficient code.
900 if (lhsTy->isRealFloatingType()) {
901 QualType promotedComplexElementTy;
902 if (!promotionTypeLHS.isNull()) {
903 promotedComplexElementTy =
904 cast<ComplexType>(promotionTypeLHS)->getElementType();
905 if (!cgf.getContext().hasSameUnqualifiedType(promotedComplexElementTy,
906 promotionTypeLHS))
907 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy,
908 promotedComplexElementTy, exprLoc);
909 } else {
910 if (!cgf.getContext().hasSameUnqualifiedType(complexElementTy, lhsTy))
911 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy, complexElementTy,
912 exprLoc);
913 }
914 opInfo.lhs = lhsVal;
915 } else {
916 opInfo.lhs = emitScalarToComplexCast(lhsVal, lhsTy, opInfo.ty, exprLoc);
917 }
918 }
919
920 // Expand the binary operator.
921 mlir::Value result = (this->*func)(opInfo);
922
923 // Truncate the result and store it into the LHS lvalue.
924 if (lhsTy->isAnyComplexType()) {
925 mlir::Value resultValue =
926 emitComplexToComplexCast(result, opInfo.ty, lhsTy, exprLoc);
927 emitStoreOfComplex(loc, resultValue, lhs, /*isInit*/ false);
928 value = RValue::getComplex(resultValue);
929 } else {
930 mlir::Value resultValue =
931 cgf.emitComplexToScalarConversion(result, opInfo.ty, lhsTy, exprLoc);
932 cgf.emitStoreOfScalar(resultValue, lhs, /*isInit*/ false);
933 value = RValue::get(resultValue);
934 }
935
936 return lhs;
937}
938
939mlir::Value ComplexExprEmitter::emitCompoundAssign(
940 const CompoundAssignOperator *e,
941 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)) {
942 RValue val;
943 LValue lv = emitCompoundAssignLValue(e, func, val);
944
945 // The result of an assignment in C is the assigned r-value.
946 if (!cgf.getLangOpts().CPlusPlus)
947 return val.getComplexValue();
948
949 // If the lvalue is non-volatile, return the computed value of the assignment.
950 if (!lv.isVolatileQualified())
951 return val.getComplexValue();
952
953 return emitLoadOfLValue(lv, e->getExprLoc());
954}
955
956LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
957 mlir::Value &value) {
958 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
959 e->getRHS()->getType()) &&
960 "Invalid assignment");
961
962 // Emit the RHS. __block variables need the RHS evaluated first.
963 value = Visit(e->getRHS());
964
965 // Compute the address to store into.
966 LValue lhs = cgf.emitLValue(e->getLHS());
967
968 // Store the result value into the LHS lvalue.
969 emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs,
970 /*isInit*/ false);
971 return lhs;
972}
973
974mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
975 mlir::Value value;
976 LValue lv = emitBinAssignLValue(e, value);
977
978 // The result of an assignment in C is the assigned r-value.
979 if (!cgf.getLangOpts().CPlusPlus)
980 return value;
981
982 // If the lvalue is non-volatile, return the computed value of the
983 // assignment.
984 if (!lv.isVolatile())
985 return value;
986
987 return emitLoadOfLValue(lv, e->getExprLoc());
988}
989
990mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
991 cgf.emitIgnoredExpr(e->getLHS());
992 return Visit(e->getRHS());
993}
994
995mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(
996 const AbstractConditionalOperator *e) {
997 mlir::Location loc = cgf.getLoc(e->getSourceRange());
998
999 // Bind the common expression if necessary.
1000 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
1001
1002 CIRGenFunction::ConditionalEvaluation eval(cgf);
1003
1004 Expr *cond = e->getCond()->IgnoreParens();
1005 mlir::Value condValue = cgf.evaluateExprAsBool(cond);
1006
1007 return cir::TernaryOp::create(
1008 builder, loc, condValue,
1009 /*thenBuilder=*/
1010 [&](mlir::OpBuilder &b, mlir::Location loc) {
1011 eval.beginEvaluation();
1012 mlir::Value trueValue = Visit(e->getTrueExpr());
1013 cir::YieldOp::create(b, loc, trueValue);
1014 eval.endEvaluation();
1015 },
1016 /*elseBuilder=*/
1017 [&](mlir::OpBuilder &b, mlir::Location loc) {
1018 eval.beginEvaluation();
1019 mlir::Value falseValue = Visit(e->getFalseExpr());
1020 cir::YieldOp::create(b, loc, falseValue);
1021 eval.endEvaluation();
1022 })
1023 .getResult();
1024}
1025
1026mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
1027 return Visit(e->getChosenSubExpr());
1028}
1029
1030mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
1031 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1032 if (e->getNumInits() == 2) {
1033 mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
1034 mlir::Value imag = cgf.emitScalarExpr(e->getInit(1));
1035 return builder.createComplexCreate(loc, real, imag);
1036 }
1037
1038 if (e->getNumInits() == 1)
1039 return Visit(e->getInit(0));
1040
1041 assert(e->getNumInits() == 0 && "Unexpected number of inits");
1042 mlir::Type complexTy = cgf.convertType(e->getType());
1043 return builder.getNullValue(complexTy, loc);
1044}
1045
1046mlir::Value ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *e) {
1047 return cgf.emitVAArg(e);
1048}
1049
1050//===----------------------------------------------------------------------===//
1051// Entry Point into this File
1052//===----------------------------------------------------------------------===//
1053
1054/// EmitComplexExpr - Emit the computation of the specified expression of
1055/// complex type, ignoring the result.
1057 assert(e && getComplexType(e->getType()) &&
1058 "Invalid complex expression to emit");
1059
1060 return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));
1061}
1062
1064 bool isInit) {
1065 assert(e && getComplexType(e->getType()) &&
1066 "Invalid complex expression to emit");
1067 ComplexExprEmitter emitter(*this);
1068 mlir::Value value = emitter.Visit(const_cast<Expr *>(e));
1069 emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit);
1070}
1071
1072/// EmitStoreOfComplex - Store a complex number into the specified l-value.
1073void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
1074 LValue dest, bool isInit) {
1075 ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
1076}
1077
1079 return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);
1080}
1081
1083 assert(e->getOpcode() == BO_Assign && "Expected assign op");
1084
1085 mlir::Value value; // ignored
1086 LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
1087 if (getLangOpts().OpenMP)
1088 cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
1089
1090 return lvalue;
1091}
1092
1094 mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &);
1095
1097 switch (op) {
1098 case BO_MulAssign:
1099 return &ComplexExprEmitter::emitBinMul;
1100 case BO_DivAssign:
1101 return &ComplexExprEmitter::emitBinDiv;
1102 case BO_SubAssign:
1103 return &ComplexExprEmitter::emitBinSub;
1104 case BO_AddAssign:
1105 return &ComplexExprEmitter::emitBinAdd;
1106 default:
1107 llvm_unreachable("unexpected complex compound assignment");
1108 }
1109}
1110
1112 const CompoundAssignOperator *e) {
1114 RValue val;
1115 return ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, val);
1116}
1117
1119 LValue lv) {
1120 mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc());
1121 mlir::Location loc = getLoc(e->getExprLoc());
1122
1123 // Increment/decrement only the real component of the complex value.
1124 mlir::Value real = builder.createComplexReal(loc, inVal);
1125 mlir::Value imag = builder.createComplexImag(loc, inVal);
1126
1127 mlir::Value resultReal;
1128 if (cir::isFPOrVectorOfFPType(real.getType())) {
1129 auto fpType = mlir::cast<cir::FPTypeInterface>(real.getType());
1130 mlir::Value amount = builder.getConstFP(
1131 loc, real.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
1132 resultReal = e->isIncrementOp() ? builder.createFAdd(loc, real, amount)
1133 : builder.createFSub(loc, real, amount);
1134 } else {
1135 resultReal = e->isIncrementOp() ? builder.createInc(loc, real)
1136 : builder.createDec(loc, real);
1137 }
1138
1139 mlir::Value incVal = builder.createComplexCreate(loc, resultReal, imag);
1140
1141 // Store the updated result through the lvalue.
1142 emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false);
1143
1144 if (getLangOpts().OpenMP)
1145 cgm.errorNYI(loc, "emitComplexPrePostIncDec OpenMP");
1146
1147 // If this is a postinc, return the value read from memory, otherwise use the
1148 // updated value.
1149 return e->isPrefix() ? incVal : inVal;
1150}
1151
1153 const CompoundAssignOperator *e, mlir::Value &result) {
1154 // Key Instructions: Don't need to create an atom group here; one will already
1155 // be active through scalar handling code.
1157 RValue value;
1158 LValue ret = ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, value);
1159 result = value.getValue();
1160 return ret;
1161}
#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)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value 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 createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createMinus(mlir::Location loc, mlir::Value input, bool nsw=false)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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:4537
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4543
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4549
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4044
Expr * getLHS() const
Definition Expr.h:4094
SourceLocation getExprLoc() const
Definition Expr.h:4085
Expr * getRHS() const
Definition Expr.h:4096
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:4257
Opcode getOpcode() const
Definition Expr.h:4089
bool isValid() const
Definition Address.h:77
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)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv)
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)
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)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
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.
void errorUnsupported(const Stmt *s, llvm::StringRef type)
Print out an error that codegen doesn't support the specified stmt yet.
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:1112
A rewritten comparison expression that was originally written using operator syntax.
Definition ExprCXX.h:290
SourceLocation getExprLoc() const LLVM_READONLY
Definition ExprCXX.h:345
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1609
CastKind getCastKind() const
Definition Expr.h:3726
bool changesVolatileQualification() const
Return.
Definition Expr.h:3816
Expr * getSubExpr()
Definition Expr.h:3732
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4890
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3339
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4306
QualType getComputationLHSType() const
Definition Expr.h:4340
QualType getComputationResultType() const
Definition Expr.h:4343
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:3095
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
const Expr * getSubExpr() const
Definition Expr.h:1068
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6471
const Expr * getSubExpr() const
Definition Expr.h:1749
unsigned getNumInits() const
Definition Expr.h:5338
const Expr * getInit(unsigned Init) const
Definition Expr.h:5360
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:3447
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:1214
Expr * getSelectedExpr() const
Definition ExprCXX.h:4639
const Expr * getSubExpr() const
Definition Expr.h:2205
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:6893
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:1661
QualType getAtomicUnqualifiedType() const
Remove all qualifiers including _Atomic.
Definition Type.cpp:1719
Encodes a location in the source.
CompoundStmt * getSubStmt()
Definition Expr.h:4618
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
void dump() const
Dumps the specified AST fragment and all subtrees to llvm::errs().
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9094
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9344
bool isReferenceType() const
Definition TypeBase.h:8708
bool isAnyComplexType() const
Definition TypeBase.h:8819
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2405
bool isFloatingType() const
Definition Type.cpp:2389
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2250
SourceLocation getExprLoc() const
Definition Expr.h:2374
Expr * getSubExpr() const
Definition Expr.h:2291
static bool isIncrementOp(Opcode Op)
Definition Expr.h:2332
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2325
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
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 fastMathFlags()