clang 24.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 return Visit(e->getSemanticForm());
277 }
278
279 // Compound assignments.
280 mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
281 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
282 }
283 mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
284 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
285 }
286 mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) {
287 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul);
288 }
289 mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) {
290 return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv);
291 }
292
293 // GCC rejects rem/and/or/xor for integer complex.
294 // Logical and/or always return int, never complex.
295
296 // No comparisons produce a complex result.
297
298 LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
299 mlir::Value VisitBinAssign(const BinaryOperator *e);
300 mlir::Value VisitBinComma(const BinaryOperator *e);
301
302 mlir::Value
303 VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
304 mlir::Value VisitChooseExpr(ChooseExpr *e);
305
306 mlir::Value VisitInitListExpr(InitListExpr *e);
307
308 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
309 return emitLoadOfLValue(e);
310 }
311
312 mlir::Value VisitVAArgExpr(VAArgExpr *e);
313
314 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
315 return cgf.emitAtomicExpr(e).getComplexValue();
316 }
317
318 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
319 return Visit(e->getSelectedExpr());
320 }
321};
322} // namespace
323
324//===----------------------------------------------------------------------===//
325// Utilities
326//===----------------------------------------------------------------------===//
327
328/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
329/// load the real and imaginary pieces, returning them as Real/Imag.
330mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
331 SourceLocation loc) {
332 assert(lv.isSimple() && "non-simple complex l-value?");
333 if (lv.getType()->isAtomicType())
334 return cgf.emitAtomicLoad(lv, loc).getComplexValue();
335
336 const Address srcAddr = lv.getAddress();
337 return builder.createLoad(cgf.getLoc(loc), srcAddr, lv.isVolatileQualified());
338}
339
340/// EmitStoreOfComplex - Store the specified real/imag parts into the
341/// specified value pointer.
342void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
343 LValue lv, bool isInit) {
344 if (lv.getType()->isAtomicType() ||
345 (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
346 return cgf.emitAtomicStore(RValue::getComplex(val), lv, isInit);
347 }
348
349 const Address destAddr = lv.getAddress();
350 builder.createStore(loc, val, destAddr, lv.isVolatileQualified());
351}
352
353//===----------------------------------------------------------------------===//
354// Visitor Methods
355//===----------------------------------------------------------------------===//
356
357mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) {
358 cgf.cgm.errorUnsupported(e, "complex expression");
359 mlir::Type complexTy = cgf.convertType(e->getType());
360 mlir::Location loc = cgf.getLoc(e->getExprLoc());
361 return builder.getConstant(loc, cir::PoisonAttr::get(complexTy));
362}
363
364mlir::Value
365ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
366 auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
367 mlir::Type elementTy = ty.getElementType();
368 mlir::Location loc = cgf.getLoc(il->getExprLoc());
369
370 mlir::TypedAttr realValueAttr;
371 mlir::TypedAttr imagValueAttr;
372
373 if (mlir::isa<cir::IntType>(elementTy)) {
374 llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
375 realValueAttr = cir::IntAttr::get(elementTy, 0);
376 imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
377 } else {
378 assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
379 "Expected complex element type to be floating-point");
380
381 llvm::APFloat imagValue =
382 cast<FloatingLiteral>(il->getSubExpr())->getValue();
383 realValueAttr = cir::FPAttr::get(
384 elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
385 imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
386 }
387
388 auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
389 return cir::ConstantOp::create(builder, loc, complexAttr);
390}
391
392mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
394 return emitLoadOfLValue(e);
395 return cgf.emitCallExpr(e).getComplexValue();
396}
397
398mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
399 CIRGenFunction::StmtExprEvaluation eval(cgf);
400 Address retAlloca =
401 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
402 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
403 assert(retAlloca.isValid() && "Expected complex return value");
404 return emitLoadOfLValue(cgf.makeAddrLValue(retAlloca, e->getType()),
405 e->getExprLoc());
406}
407
408mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
409 QualType srcType,
410 QualType destType,
411 SourceLocation loc) {
412 if (srcType == destType)
413 return val;
414
415 // Get the src/dest element type.
416 QualType srcElemTy = srcType.getAtomicUnqualifiedType()
417 ->castAs<ComplexType>()
418 ->getElementType();
419 QualType destElemTy = destType.getAtomicUnqualifiedType()
420 ->castAs<ComplexType>()
421 ->getElementType();
422
423 cir::CastKind castOpKind;
424 if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
425 castOpKind = cir::CastKind::float_complex;
426 else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
427 castOpKind = cir::CastKind::float_complex_to_int_complex;
428 else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
429 castOpKind = cir::CastKind::int_complex_to_float_complex;
430 else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
431 castOpKind = cir::CastKind::int_complex;
432 else
433 llvm_unreachable("unexpected src type or dest type");
434
435 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
436 cgf.convertType(destType));
437}
438
439mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
440 QualType srcType,
441 QualType destType,
442 SourceLocation loc) {
443 cir::CastKind castOpKind;
444 if (srcType->isFloatingType())
445 castOpKind = cir::CastKind::float_to_complex;
446 else if (srcType->isIntegerType())
447 castOpKind = cir::CastKind::int_to_complex;
448 else
449 llvm_unreachable("unexpected src type");
450
451 return builder.createCast(cgf.getLoc(loc), castOpKind, val,
452 cgf.convertType(destType));
453}
454
455mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
456 QualType destTy) {
457 destTy = destTy.getAtomicUnqualifiedType();
458 switch (ck) {
459 case CK_Dependent:
460 llvm_unreachable("dependent type must be resolved before the CIR codegen");
461
462 // Atomic to non-atomic casts may be more than a no-op for some platforms
463 // and for some types.
464 case CK_NonAtomicToAtomic:
465 case CK_AtomicToNonAtomic:
466 case CK_NoOp:
467 case CK_LValueToRValue:
468 case CK_UserDefinedConversion:
469 return Visit(op);
470
471 case CK_LValueBitCast: {
472 LValue origLV = cgf.emitLValue(op);
473 Address addr =
474 origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
475 LValue destLV = cgf.makeAddrLValue(addr, destTy);
476 return emitLoadOfLValue(destLV, op->getExprLoc());
477 }
478
479 case CK_LValueToRValueBitCast: {
480 LValue sourceLVal = cgf.emitLValue(op);
481 Address addr = sourceLVal.getAddress().withElementType(
482 builder, cgf.convertTypeForMem(destTy));
483 LValue destLV = cgf.makeAddrLValue(addr, destTy);
485 return emitLoadOfLValue(destLV, op->getExprLoc());
486 }
487
488 case CK_BitCast:
489 case CK_BaseToDerived:
490 case CK_DerivedToBase:
491 case CK_UncheckedDerivedToBase:
492 case CK_Dynamic:
493 case CK_ToUnion:
494 case CK_ArrayToPointerDecay:
495 case CK_FunctionToPointerDecay:
496 case CK_NullToPointer:
497 case CK_NullToMemberPointer:
498 case CK_BaseToDerivedMemberPointer:
499 case CK_DerivedToBaseMemberPointer:
500 case CK_MemberPointerToBoolean:
501 case CK_ReinterpretMemberPointer:
502 case CK_ConstructorConversion:
503 case CK_IntegralToPointer:
504 case CK_PointerToIntegral:
505 case CK_PointerToBoolean:
506 case CK_ToVoid:
507 case CK_VectorSplat:
508 case CK_IntegralCast:
509 case CK_BooleanToSignedIntegral:
510 case CK_IntegralToBoolean:
511 case CK_IntegralToFloating:
512 case CK_FloatingToIntegral:
513 case CK_FloatingToBoolean:
514 case CK_FloatingCast:
515 case CK_CPointerToObjCPointerCast:
516 case CK_BlockPointerToObjCPointerCast:
517 case CK_AnyPointerToBlockPointerCast:
518 case CK_ObjCObjectLValueCast:
519 case CK_FloatingComplexToReal:
520 case CK_FloatingComplexToBoolean:
521 case CK_IntegralComplexToReal:
522 case CK_IntegralComplexToBoolean:
523 case CK_ARCProduceObject:
524 case CK_ARCConsumeObject:
525 case CK_ARCReclaimReturnedObject:
526 case CK_ARCExtendBlockObject:
527 case CK_CopyAndAutoreleaseBlockObject:
528 case CK_BuiltinFnToFnPtr:
529 case CK_ZeroToOCLOpaqueType:
530 case CK_AddressSpaceConversion:
531 case CK_IntToOCLSampler:
532 case CK_FloatingToFixedPoint:
533 case CK_FixedPointToFloating:
534 case CK_FixedPointCast:
535 case CK_FixedPointToBoolean:
536 case CK_FixedPointToIntegral:
537 case CK_IntegralToFixedPoint:
538 case CK_MatrixCast:
539 case CK_HLSLVectorTruncation:
540 case CK_HLSLMatrixTruncation:
541 case CK_HLSLArrayRValue:
542 case CK_HLSLElementwiseCast:
543 case CK_HLSLAggregateSplatCast:
544 llvm_unreachable("invalid cast kind for complex value");
545
546 case CK_FloatingRealToComplex:
547 case CK_IntegralRealToComplex: {
548 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op);
549 return emitScalarToComplexCast(cgf.emitScalarExpr(op), op->getType(),
550 destTy, op->getExprLoc());
551 }
552
553 case CK_FloatingComplexCast:
554 case CK_FloatingComplexToIntegralComplex:
555 case CK_IntegralComplexCast:
556 case CK_IntegralComplexToFloatingComplex: {
557 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op);
558 return emitComplexToComplexCast(Visit(op), op->getType(), destTy,
559 op->getExprLoc());
560 }
561 }
562
563 llvm_unreachable("unknown cast resulting in complex value");
564}
565
566mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
567 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
568 mlir::Value result = VisitUnaryPlus(e, promotionTy);
569 if (!promotionTy.isNull())
570 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
571 return result;
572}
573
574mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e,
575 QualType promotionType) {
576 if (!promotionType.isNull())
577 return cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
578 return Visit(e->getSubExpr());
579}
580
581mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
582 QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
583 mlir::Value result = VisitUnaryMinus(e, promotionTy);
584 if (!promotionTy.isNull())
585 return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
586 return result;
587}
588
589mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e,
590 QualType promotionType) {
591 mlir::Value op;
592 if (!promotionType.isNull())
593 op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
594 else
595 op = Visit(e->getSubExpr());
596
597 // Negate each component of the complex value.
598 mlir::Location loc = cgf.getLoc(e->getExprLoc());
599 mlir::Value real = builder.createComplexReal(loc, op);
600 mlir::Value imag = builder.createComplexImag(loc, op);
601
602 mlir::Value resultReal;
603 mlir::Value resultImag;
604 if (cir::isFPOrVectorOfFPType(real.getType())) {
605 resultReal = builder.createFNeg(loc, real);
606 resultImag = builder.createFNeg(loc, imag);
607 } else {
608 resultReal = builder.createMinus(loc, real);
609 resultImag = builder.createMinus(loc, imag);
610 }
611
612 return builder.createComplexCreate(loc, resultReal, resultImag);
613}
614
615mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
616 mlir::Value op = Visit(e->getSubExpr());
617 return builder.createComplexConj(cgf.getLoc(e->getExprLoc()), op);
618}
619
620mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
622 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op.fpFeatures);
623
624 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
625 mlir::isa<cir::ComplexType>(op.rhs.getType()))
626 return builder.createComplexAdd(op.loc, op.lhs, op.rhs);
627
628 auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
629 return cir::isFPOrVectorOfFPType(a.getType())
630 ? builder.createFAdd(loc, a, b)
631 : builder.createAdd(loc, a, b);
632 };
633
634 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
635 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
636 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
637 mlir::Value newReal = createAdd(op.loc, real, op.rhs);
638 return builder.createComplexCreate(op.loc, newReal, imag);
639 }
640
641 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
642 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
643 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
644 mlir::Value newReal = createAdd(op.loc, op.lhs, real);
645 return builder.createComplexCreate(op.loc, newReal, imag);
646}
647
648mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
650 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op.fpFeatures);
651
652 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
653 mlir::isa<cir::ComplexType>(op.rhs.getType()))
654 return builder.createComplexSub(op.loc, op.lhs, op.rhs);
655
656 auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
657 return cir::isFPOrVectorOfFPType(a.getType())
658 ? builder.createFSub(loc, a, b)
659 : builder.createSub(loc, a, b);
660 };
661
662 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
663 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
664 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
665 mlir::Value newReal = createSub(op.loc, real, op.rhs);
666 return builder.createComplexCreate(op.loc, newReal, imag);
667 }
668
669 auto createNeg = [&](mlir::Location loc, mlir::Value a) {
670 return cir::isFPOrVectorOfFPType(a.getType()) ? builder.createFNeg(loc, a)
671 : builder.createNeg(loc, a);
672 };
673
674 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
675 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
676 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
677 mlir::Value newReal = createSub(op.loc, op.lhs, real);
678 mlir::Value newImag = createNeg(op.loc, imag);
679 return builder.createComplexCreate(op.loc, newReal, newImag);
680}
681
682static cir::ComplexRangeKind
684 switch (range) {
686 return cir::ComplexRangeKind::Full;
688 return cir::ComplexRangeKind::Improved;
690 return cir::ComplexRangeKind::Promoted;
692 return cir::ComplexRangeKind::Basic;
694 // The default value for ComplexRangeKind is Full if no option is selected
695 return cir::ComplexRangeKind::Full;
696 }
697}
698
699mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
701 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op.fpFeatures);
702
703 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
704 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
705 cir::ComplexRangeKind rangeKind =
706 getComplexRangeAttr(op.fpFeatures.getComplexRange());
707 return builder.createComplexMul(op.loc, op.lhs, op.rhs, rangeKind);
708 }
709
710 auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
711 return cir::isFPOrVectorOfFPType(a.getType())
712 ? builder.createFMul(loc, a, b)
713 : builder.createMul(loc, a, b);
714 };
715
716 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
717 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
718 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
719 mlir::Value newReal = createMul(op.loc, real, op.rhs);
720 mlir::Value newImag = createMul(op.loc, imag, op.rhs);
721 return builder.createComplexCreate(op.loc, newReal, newImag);
722 }
723
724 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
725 mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
726 mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
727 mlir::Value newReal = createMul(op.loc, op.lhs, real);
728 mlir::Value newImag = createMul(op.loc, op.lhs, imag);
729 return builder.createComplexCreate(op.loc, newReal, newImag);
730}
731
732mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) {
734 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, op.fpFeatures);
735
736 // Handle division between two complex values. In the case of complex integer
737 // types mixed with scalar integers, the scalar integer type will always be
738 // promoted to a complex integer value with a zero imaginary component when
739 // the AST is formed.
740 if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
741 mlir::isa<cir::ComplexType>(op.rhs.getType())) {
742 cir::ComplexRangeKind rangeKind =
743 getComplexRangeAttr(op.fpFeatures.getComplexRange());
744 return builder.createComplexDiv(op.loc, op.lhs, op.rhs, rangeKind);
745 }
746
747 // The C99 standard (G.5.1) defines division of a complex value by a real
748 // value in the following simplified form.
749 if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
750 assert(mlir::cast<cir::ComplexType>(op.lhs.getType()).getElementType() ==
751 op.rhs.getType());
752 mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
753 mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
754 mlir::Value newReal = builder.createFDiv(op.loc, real, op.rhs);
755 mlir::Value newImag = builder.createFDiv(op.loc, imag, op.rhs);
756 return builder.createComplexCreate(op.loc, newReal, newImag);
757 }
758
759 assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
760 cir::ConstantOp nullValue = builder.getNullValue(op.lhs.getType(), op.loc);
761 mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue);
762 cir::ComplexRangeKind rangeKind =
763 getComplexRangeAttr(op.fpFeatures.getComplexRange());
764 return builder.createComplexDiv(op.loc, lhs, op.rhs, rangeKind);
765}
766
767mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result,
768 QualType unPromotionType) {
769 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
770 "integral complex will never be promoted");
771 return builder.createCast(cir::CastKind::float_complex, result,
772 convertType(unPromotionType));
773}
774
775mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result,
776 QualType promotionType) {
777 assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
778 "integral complex will never be promoted");
779 return builder.createCast(cir::CastKind::float_complex, result,
780 convertType(promotionType));
781}
782
783mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
784 QualType promotionTy) {
785 e = e->IgnoreParens();
786 if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
787 switch (bo->getOpcode()) {
788#define HANDLE_BINOP(OP) \
789 case BO_##OP: \
790 return emitBin##OP(emitBinOps(bo, promotionTy));
791 HANDLE_BINOP(Add)
792 HANDLE_BINOP(Sub)
793 HANDLE_BINOP(Mul)
794 HANDLE_BINOP(Div)
795#undef HANDLE_BINOP
796 default:
797 break;
798 }
799 } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) {
800 switch (unaryOp->getOpcode()) {
801 case UO_Plus:
802 return VisitUnaryPlus(unaryOp, promotionTy);
803 case UO_Minus:
804 return VisitUnaryMinus(unaryOp, promotionTy);
805 default:
806 break;
807 }
808 }
809
810 mlir::Value result = Visit(const_cast<Expr *>(e));
811 if (!promotionTy.isNull())
812 return cgf.emitPromotedValue(result, promotionTy);
813
814 return result;
815}
816
818 QualType promotionType) {
819 return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
820}
821
822mlir::Value
823ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
824 QualType promotionTy) {
825 if (e->getType()->isAnyComplexType()) {
826 if (!promotionTy.isNull())
827 return cgf.emitPromotedComplexExpr(e, promotionTy);
828 return Visit(const_cast<Expr *>(e));
829 }
830
831 if (!promotionTy.isNull()) {
832 QualType complexElementTy =
833 promotionTy->castAs<ComplexType>()->getElementType();
834 return cgf.emitPromotedScalarExpr(e, complexElementTy);
835 }
836 return cgf.emitScalarExpr(e);
837}
838
839ComplexExprEmitter::BinOpInfo
840ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
841 BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};
842 binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);
843 binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);
844 binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;
845 binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
846 return binOpInfo;
847}
848
849LValue ComplexExprEmitter::emitCompoundAssignLValue(
850 const CompoundAssignOperator *e,
851 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) {
852 QualType lhsTy = e->getLHS()->getType().getAtomicUnqualifiedType();
853 QualType rhsTy = e->getRHS()->getType();
854 SourceLocation exprLoc = e->getExprLoc();
855 mlir::Location loc = cgf.getLoc(exprLoc);
856
857 BinOpInfo opInfo{loc};
858 opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
859
860 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, opInfo.fpFeatures);
861
862 // Load the RHS and LHS operands.
863 // __block variables need to have the rhs evaluated first, plus this should
864 // improve codegen a little.
865 QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
866 opInfo.ty = promotionTypeCR.isNull() ? e->getComputationResultType()
867 : promotionTypeCR;
868
869 QualType complexElementTy =
870 opInfo.ty->castAs<ComplexType>()->getElementType();
871 QualType promotionTypeRHS = getPromotionType(rhsTy);
872
873 // The RHS should have been converted to the computation type.
874 if (e->getRHS()->getType()->isRealFloatingType()) {
875 if (!promotionTypeRHS.isNull()) {
876 opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
877 } else {
878 assert(cgf.getContext().hasSameUnqualifiedType(complexElementTy, rhsTy));
879 opInfo.rhs = cgf.emitScalarExpr(e->getRHS());
880 }
881 } else {
882 if (!promotionTypeRHS.isNull()) {
883 opInfo.rhs = cgf.emitPromotedComplexExpr(e->getRHS(), promotionTypeRHS);
884 } else {
885 assert(cgf.getContext().hasSameUnqualifiedType(opInfo.ty, rhsTy));
886 opInfo.rhs = Visit(e->getRHS());
887 }
888 }
889
890 LValue lhs = cgf.emitLValue(e->getLHS());
891
892 // Load from the l-value and convert it.
893 QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
894 if (lhsTy->isAnyComplexType()) {
895 mlir::Value lhsValue = emitLoadOfLValue(lhs, exprLoc);
896 QualType destTy = promotionTypeLHS.isNull() ? opInfo.ty : promotionTypeLHS;
897 opInfo.lhs = emitComplexToComplexCast(lhsValue, lhsTy, destTy, exprLoc);
898 } else {
899 mlir::Value lhsVal = cgf.emitLoadOfScalar(lhs, exprLoc);
900 // For floating point real operands we can directly pass the scalar form
901 // to the binary operator emission and potentially get more efficient code.
902 if (lhsTy->isRealFloatingType()) {
903 QualType promotedComplexElementTy;
904 if (!promotionTypeLHS.isNull()) {
905 promotedComplexElementTy =
906 cast<ComplexType>(promotionTypeLHS)->getElementType();
907 if (!cgf.getContext().hasSameUnqualifiedType(promotedComplexElementTy,
908 promotionTypeLHS))
909 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy,
910 promotedComplexElementTy, exprLoc);
911 } else {
912 if (!cgf.getContext().hasSameUnqualifiedType(complexElementTy, lhsTy))
913 lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy, complexElementTy,
914 exprLoc);
915 }
916 opInfo.lhs = lhsVal;
917 } else {
918 opInfo.lhs = emitScalarToComplexCast(lhsVal, lhsTy, opInfo.ty, exprLoc);
919 }
920 }
921
922 // Expand the binary operator.
923 mlir::Value result = (this->*func)(opInfo);
924
925 // Truncate the result and store it into the LHS lvalue.
926 if (lhsTy->isAnyComplexType()) {
927 mlir::Value resultValue =
928 emitComplexToComplexCast(result, opInfo.ty, lhsTy, exprLoc);
929 emitStoreOfComplex(loc, resultValue, lhs, /*isInit*/ false);
930 value = RValue::getComplex(resultValue);
931 } else {
932 mlir::Value resultValue =
933 cgf.emitComplexToScalarConversion(result, opInfo.ty, lhsTy, exprLoc);
934 cgf.emitStoreOfScalar(resultValue, lhs, /*isInit*/ false);
935 value = RValue::get(resultValue);
936 }
937
938 return lhs;
939}
940
941mlir::Value ComplexExprEmitter::emitCompoundAssign(
942 const CompoundAssignOperator *e,
943 mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)) {
944 RValue val;
945 LValue lv = emitCompoundAssignLValue(e, func, val);
946
947 // The result of an assignment in C is the assigned r-value.
948 if (!cgf.getLangOpts().CPlusPlus)
949 return val.getComplexValue();
950
951 // If the lvalue is non-volatile, return the computed value of the assignment.
952 if (!lv.isVolatileQualified())
953 return val.getComplexValue();
954
955 return emitLoadOfLValue(lv, e->getExprLoc());
956}
957
958LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
959 mlir::Value &value) {
960 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
961 e->getRHS()->getType()) &&
962 "Invalid assignment");
963
964 // Emit the RHS. __block variables need the RHS evaluated first.
965 value = Visit(e->getRHS());
966
967 // Compute the address to store into.
968 LValue lhs = cgf.emitLValue(e->getLHS());
969
970 // Store the result value into the LHS lvalue.
971 emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs,
972 /*isInit*/ false);
973 return lhs;
974}
975
976mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
977 mlir::Value value;
978 LValue lv = emitBinAssignLValue(e, value);
979
980 // The result of an assignment in C is the assigned r-value.
981 if (!cgf.getLangOpts().CPlusPlus)
982 return value;
983
984 // If the lvalue is non-volatile, return the computed value of the
985 // assignment.
986 if (!lv.isVolatile())
987 return value;
988
989 return emitLoadOfLValue(lv, e->getExprLoc());
990}
991
992mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
993 cgf.emitIgnoredExpr(e->getLHS());
994 return Visit(e->getRHS());
995}
996
997mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(
998 const AbstractConditionalOperator *e) {
999 mlir::Location loc = cgf.getLoc(e->getSourceRange());
1000
1001 // Bind the common expression if necessary.
1002 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
1003
1004 Expr *cond = e->getCond()->IgnoreParens();
1005 mlir::Value condValue = cgf.evaluateExprAsBool(cond);
1006
1007 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1008
1009 return cir::TernaryOp::create(
1010 builder, loc, condValue,
1011 /*trueBuilder=*/
1012 [&](mlir::OpBuilder &b, mlir::Location loc) {
1013 eval.beginEvaluation();
1014 mlir::Value trueValue = Visit(e->getTrueExpr());
1015 cir::YieldOp::create(b, loc, trueValue);
1016 eval.endEvaluation();
1017 },
1018 /*falseBuilder=*/
1019 [&](mlir::OpBuilder &b, mlir::Location loc) {
1020 eval.beginEvaluation();
1021 mlir::Value falseValue = Visit(e->getFalseExpr());
1022 cir::YieldOp::create(b, loc, falseValue);
1023 eval.endEvaluation();
1024 })
1025 .getResult();
1026}
1027
1028mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
1029 return Visit(e->getChosenSubExpr());
1030}
1031
1032mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
1033 mlir::Location loc = cgf.getLoc(e->getExprLoc());
1034 if (e->getNumInits() == 2) {
1035 mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
1036 mlir::Value imag = cgf.emitScalarExpr(e->getInit(1));
1037 return builder.createComplexCreate(loc, real, imag);
1038 }
1039
1040 if (e->getNumInits() == 1)
1041 return Visit(e->getInit(0));
1042
1043 assert(e->getNumInits() == 0 && "Unexpected number of inits");
1044 mlir::Type complexTy = cgf.convertType(e->getType());
1045 return builder.getNullValue(complexTy, loc);
1046}
1047
1048mlir::Value ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *e) {
1049 return cgf.emitVAArg(e);
1050}
1051
1052//===----------------------------------------------------------------------===//
1053// Entry Point into this File
1054//===----------------------------------------------------------------------===//
1055
1056/// EmitComplexExpr - Emit the computation of the specified expression of
1057/// complex type, ignoring the result.
1059 assert(e && getComplexType(e->getType()) &&
1060 "Invalid complex expression to emit");
1061
1062 return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));
1063}
1064
1066 bool isInit) {
1067 assert(e && getComplexType(e->getType()) &&
1068 "Invalid complex expression to emit");
1069 ComplexExprEmitter emitter(*this);
1070 mlir::Value value = emitter.Visit(const_cast<Expr *>(e));
1071 emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit);
1072}
1073
1074/// EmitStoreOfComplex - Store a complex number into the specified l-value.
1075void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
1076 LValue dest, bool isInit) {
1077 ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
1078}
1079
1081 return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);
1082}
1083
1085 assert(e->getOpcode() == BO_Assign && "Expected assign op");
1086
1087 mlir::Value value; // ignored
1088 LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
1089 if (getLangOpts().OpenMP)
1090 cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
1091
1092 return lvalue;
1093}
1094
1096 mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &);
1097
1099 switch (op) {
1100 case BO_MulAssign:
1101 return &ComplexExprEmitter::emitBinMul;
1102 case BO_DivAssign:
1103 return &ComplexExprEmitter::emitBinDiv;
1104 case BO_SubAssign:
1105 return &ComplexExprEmitter::emitBinSub;
1106 case BO_AddAssign:
1107 return &ComplexExprEmitter::emitBinAdd;
1108 default:
1109 llvm_unreachable("unexpected complex compound assignment");
1110 }
1111}
1112
1114 const CompoundAssignOperator *e) {
1116 RValue val;
1117 return ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, val);
1118}
1119
1121 LValue lv) {
1122 mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc());
1123 mlir::Location loc = getLoc(e->getExprLoc());
1124
1125 // Increment/decrement only the real component of the complex value.
1126 mlir::Value real = builder.createComplexReal(loc, inVal);
1127 mlir::Value imag = builder.createComplexImag(loc, inVal);
1128
1129 mlir::Value resultReal;
1130 if (cir::isFPOrVectorOfFPType(real.getType())) {
1131 auto fpType = mlir::cast<cir::FPTypeInterface>(real.getType());
1132 mlir::Value amount = builder.getConstFP(
1133 loc, real.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
1134 resultReal = e->isIncrementOp() ? builder.createFAdd(loc, real, amount)
1135 : builder.createFSub(loc, real, amount);
1136 } else {
1137 resultReal = e->isIncrementOp() ? builder.createInc(loc, real)
1138 : builder.createDec(loc, real);
1139 }
1140
1141 mlir::Value incVal = builder.createComplexCreate(loc, resultReal, imag);
1142
1143 // Store the updated result through the lvalue.
1144 emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false);
1145
1146 if (getLangOpts().OpenMP)
1147 cgm.errorNYI(loc, "emitComplexPrePostIncDec OpenMP");
1148
1149 // If this is a postinc, return the value read from memory, otherwise use the
1150 // updated value.
1151 return e->isPrefix() ? incVal : inVal;
1152}
1153
1155 const CompoundAssignOperator *e, mlir::Value &result) {
1156 // Key Instructions: Don't need to create an atom group here; one will already
1157 // be active through scalar handling code.
1159 RValue value;
1160 LValue ret = ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, value);
1161 result = value.getValue();
1162 return ret;
1163}
#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 createComplexMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, cir::ComplexRangeKind rangeKind)
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 createComplexSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createComplexDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, cir::ComplexRangeKind rangeKind)
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 createComplexAdd(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:4579
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4585
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4591
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4086
Expr * getLHS() const
Definition Expr.h:4136
SourceLocation getExprLoc() const
Definition Expr.h:4127
Expr * getRHS() const
Definition Expr.h:4138
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Definition Expr.h:4299
Opcode getOpcode() const
Definition Expr.h:4131
bool isValid() const
Definition Address.h:77
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
LValue getReferenceLValue(CIRGenFunction &cgf, const 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.
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:1137
A rewritten comparison expression that was originally written using operator syntax.
Definition ExprCXX.h:291
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:309
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1635
CastKind getCastKind() const
Definition Expr.h:3768
bool changesVolatileQualification() const
Return.
Definition Expr.h:3858
Expr * getSubExpr()
Definition Expr.h:3774
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4932
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3362
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4348
QualType getComputationLHSType() const
Definition Expr.h:4382
QualType getComputationResultType() const
Definition Expr.h:4385
This represents one expression.
Definition Expr.h:113
bool isGLValue() const
Definition Expr.h:288
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
const Expr * getSubExpr() const
Definition Expr.h:1086
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6522
const Expr * getSubExpr() const
Definition Expr.h:1767
unsigned getNumInits() const
Definition Expr.h:5389
const Expr * getInit(unsigned Init) const
Definition Expr.h:5411
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:3489
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:1232
Expr * getSelectedExpr() const
Definition ExprCXX.h:4693
const Expr * getSubExpr() const
Definition Expr.h:2247
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:6944
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
bool UseExcessPrecision(const ASTContext &Ctx)
Definition Type.cpp:1775
QualType getAtomicUnqualifiedType() const
Remove all qualifiers including _Atomic.
Definition Type.cpp:1841
Encodes a location in the source.
CompoundStmt * getSubStmt()
Definition Expr.h:4660
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
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:9116
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9366
bool isReferenceType() const
Definition TypeBase.h:8707
bool isAnyComplexType() const
Definition TypeBase.h:8818
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2533
bool isFloatingType() const
Definition Type.cpp:2517
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2292
SourceLocation getExprLoc() const
Definition Expr.h:2416
Expr * getSubExpr() const
Definition Expr.h:2333
static bool isIncrementOp(Opcode Op)
Definition Expr.h:2374
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2367
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool fastMathFlags()