xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 #include "CIRGenBuilder.h"
2 #include "CIRGenFunction.h"
3 
4 #include "clang/AST/StmtVisitor.h"
5 
6 using namespace clang;
7 using namespace clang::CIRGen;
8 
9 namespace {
10 class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
11   CIRGenFunction &cgf;
12   CIRGenBuilderTy &builder;
13 
14 public:
15   explicit ComplexExprEmitter(CIRGenFunction &cgf)
16       : cgf(cgf), builder(cgf.getBuilder()) {}
17 
18   //===--------------------------------------------------------------------===//
19   //                               Utilities
20   //===--------------------------------------------------------------------===//
21 
22   LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
23 
24   mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
25 
26   mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,
27                            Expr *e);
28 
29   /// Given an expression with complex type that represents a value l-value,
30   /// this method emits the address of the l-value, then loads and returns the
31   /// result.
32   mlir::Value emitLoadOfLValue(const Expr *e) {
33     return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());
34   }
35 
36   mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
37   /// Store the specified real/imag parts into the
38   /// specified value pointer.
39   void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
40                           bool isInit);
41 
42   mlir::Value
43   VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
44   mlir::Value VisitArraySubscriptExpr(Expr *e);
45   mlir::Value VisitBinAssign(const BinaryOperator *e);
46   mlir::Value VisitBinComma(const BinaryOperator *e);
47   mlir::Value VisitCallExpr(const CallExpr *e);
48   mlir::Value VisitCastExpr(CastExpr *e);
49   mlir::Value VisitChooseExpr(ChooseExpr *e);
50   mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e);
51   mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
52   mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
53   mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
54   mlir::Value VisitInitListExpr(const InitListExpr *e);
55   mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
56   mlir::Value VisitParenExpr(ParenExpr *e);
57   mlir::Value
58   VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);
59   mlir::Value VisitUnaryDeref(const Expr *e);
60 
61   struct BinOpInfo {
62     mlir::Location loc;
63     mlir::Value lhs{};
64     mlir::Value rhs{};
65     QualType ty{}; // Computation Type.
66     FPOptions fpFeatures{};
67   };
68 
69   BinOpInfo emitBinOps(const BinaryOperator *e,
70                        QualType promotionTy = QualType());
71 
72   mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
73 
74   mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
75 
76   mlir::Value emitBinAdd(const BinOpInfo &op);
77   mlir::Value emitBinSub(const BinOpInfo &op);
78 
79   QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
80     if (auto *complexTy = ty->getAs<ComplexType>()) {
81       QualType elementTy = complexTy->getElementType();
82       if (isDivOpCode && elementTy->isFloatingType() &&
83           cgf.getLangOpts().getComplexRange() ==
84               LangOptions::ComplexRangeKind::CX_Promoted) {
85         cgf.cgm.errorNYI("HigherPrecisionTypeForComplexArithmetic");
86         return QualType();
87       }
88 
89       if (elementTy.UseExcessPrecision(cgf.getContext()))
90         return cgf.getContext().getComplexType(cgf.getContext().FloatTy);
91     }
92 
93     if (ty.UseExcessPrecision(cgf.getContext()))
94       return cgf.getContext().FloatTy;
95     return QualType();
96   }
97 
98 #define HANDLEBINOP(OP)                                                        \
99   mlir::Value VisitBin##OP(const BinaryOperator *e) {                          \
100     QualType promotionTy = getPromotionType(                                   \
101         e->getType(), e->getOpcode() == BinaryOperatorKind::BO_Div);           \
102     mlir::Value result = emitBin##OP(emitBinOps(e, promotionTy));              \
103     if (!promotionTy.isNull())                                                 \
104       cgf.cgm.errorNYI("Binop emitUnPromotedValue");                           \
105     return result;                                                             \
106   }
107 
108   HANDLEBINOP(Add)
109   HANDLEBINOP(Sub)
110 #undef HANDLEBINOP
111 };
112 } // namespace
113 
114 static const ComplexType *getComplexType(QualType type) {
115   type = type.getCanonicalType();
116   if (const ComplexType *comp = dyn_cast<ComplexType>(type))
117     return comp;
118   return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
119 }
120 
121 LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
122                                                mlir::Value &value) {
123   assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
124                                                  e->getRHS()->getType()) &&
125          "Invalid assignment");
126 
127   // Emit the RHS.  __block variables need the RHS evaluated first.
128   value = Visit(e->getRHS());
129 
130   // Compute the address to store into.
131   LValue lhs = cgf.emitLValue(e->getLHS());
132 
133   // Store the result value into the LHS lvalue.
134   emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);
135   return lhs;
136 }
137 
138 mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
139                                          QualType destTy) {
140   switch (ck) {
141   case CK_NoOp:
142   case CK_LValueToRValue:
143     return Visit(op);
144   default:
145     break;
146   }
147   cgf.cgm.errorNYI("ComplexType Cast");
148   return {};
149 }
150 
151 mlir::Value ComplexExprEmitter::emitConstant(
152     const CIRGenFunction::ConstantEmission &constant, Expr *e) {
153   assert(constant && "not a constant");
154   if (constant.isReference())
155     return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),
156                             e->getExprLoc());
157 
158   mlir::TypedAttr valueAttr = constant.getValue();
159   return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);
160 }
161 
162 mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
163                                                  SourceLocation loc) {
164   assert(lv.isSimple() && "non-simple complex l-value?");
165   if (lv.getType()->isAtomicType())
166     cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");
167 
168   const Address srcAddr = lv.getAddress();
169   return builder.createLoad(cgf.getLoc(loc), srcAddr);
170 }
171 
172 void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
173                                             LValue lv, bool isInit) {
174   if (lv.getType()->isAtomicType() ||
175       (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
176     cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");
177     return;
178   }
179 
180   const Address destAddr = lv.getAddress();
181   builder.createStore(loc, val, destAddr);
182 }
183 
184 mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(
185     const AbstractConditionalOperator *e) {
186   mlir::Value condValue = Visit(e->getCond());
187   mlir::Location loc = cgf.getLoc(e->getSourceRange());
188 
189   return builder
190       .create<cir::TernaryOp>(
191           loc, condValue,
192           /*thenBuilder=*/
193           [&](mlir::OpBuilder &b, mlir::Location loc) {
194             mlir::Value trueValue = Visit(e->getTrueExpr());
195             b.create<cir::YieldOp>(loc, trueValue);
196           },
197           /*elseBuilder=*/
198           [&](mlir::OpBuilder &b, mlir::Location loc) {
199             mlir::Value falseValue = Visit(e->getFalseExpr());
200             b.create<cir::YieldOp>(loc, falseValue);
201           })
202       .getResult();
203 }
204 
205 mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) {
206   return emitLoadOfLValue(e);
207 }
208 
209 mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
210   mlir::Value value;
211   LValue lv = emitBinAssignLValue(e, value);
212 
213   // The result of an assignment in C is the assigned r-value.
214   if (!cgf.getLangOpts().CPlusPlus)
215     return value;
216 
217   // If the lvalue is non-volatile, return the computed value of the
218   // assignment.
219   if (!lv.isVolatile())
220     return value;
221 
222   return emitLoadOfLValue(lv, e->getExprLoc());
223 }
224 
225 mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
226   cgf.emitIgnoredExpr(e->getLHS());
227   return Visit(e->getRHS());
228 }
229 
230 mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
231   if (e->getCallReturnType(cgf.getContext())->isReferenceType())
232     return emitLoadOfLValue(e);
233 
234   return cgf.emitCallExpr(e).getValue();
235 }
236 
237 mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) {
238   if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) {
239     // Bind VLAs in the cast type.
240     if (ece->getType()->isVariablyModifiedType()) {
241       cgf.cgm.errorNYI("VisitCastExpr Bind VLAs in the cast type");
242       return {};
243     }
244   }
245 
246   if (e->changesVolatileQualification())
247     return emitLoadOfLValue(e);
248 
249   return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
250 }
251 
252 mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
253   return Visit(e->getChosenSubExpr());
254 }
255 
256 mlir::Value
257 ComplexExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
258   mlir::Location loc = cgf.getLoc(e->getExprLoc());
259   mlir::Type complexTy = cgf.convertType(e->getType());
260   return builder.getNullValue(complexTy, loc);
261 }
262 
263 mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {
264   if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
265     return emitConstant(constant, e);
266   return emitLoadOfLValue(e);
267 }
268 
269 mlir::Value
270 ComplexExprEmitter::VisitGenericSelectionExpr(GenericSelectionExpr *e) {
271   return Visit(e->getResultExpr());
272 }
273 
274 mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) {
275   // Unlike for scalars, we don't have to worry about function->ptr demotion
276   // here.
277   if (e->changesVolatileQualification())
278     return emitLoadOfLValue(e);
279   return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
280 }
281 
282 mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
283   mlir::Location loc = cgf.getLoc(e->getExprLoc());
284   if (e->getNumInits() == 2) {
285     mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
286     mlir::Value imag = cgf.emitScalarExpr(e->getInit(1));
287     return builder.createComplexCreate(loc, real, imag);
288   }
289 
290   if (e->getNumInits() == 1) {
291     cgf.cgm.errorNYI("Create Complex with InitList with size 1");
292     return {};
293   }
294 
295   assert(e->getNumInits() == 0 && "Unexpected number of inits");
296   mlir::Type complexTy = cgf.convertType(e->getType());
297   return builder.getNullValue(complexTy, loc);
298 }
299 
300 mlir::Value
301 ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
302   auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
303   mlir::Type elementTy = ty.getElementType();
304   mlir::Location loc = cgf.getLoc(il->getExprLoc());
305 
306   mlir::TypedAttr realValueAttr;
307   mlir::TypedAttr imagValueAttr;
308 
309   if (mlir::isa<cir::IntType>(elementTy)) {
310     llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
311     realValueAttr = cir::IntAttr::get(elementTy, 0);
312     imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
313   } else {
314     assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
315            "Expected complex element type to be floating-point");
316 
317     llvm::APFloat imagValue =
318         cast<FloatingLiteral>(il->getSubExpr())->getValue();
319     realValueAttr = cir::FPAttr::get(
320         elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
321     imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
322   }
323 
324   auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
325   return builder.create<cir::ConstantOp>(loc, complexAttr);
326 }
327 
328 mlir::Value ComplexExprEmitter::VisitParenExpr(ParenExpr *e) {
329   return Visit(e->getSubExpr());
330 }
331 
332 mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr(
333     SubstNonTypeTemplateParmExpr *e) {
334   return Visit(e->getReplacement());
335 }
336 
337 mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {
338   return emitLoadOfLValue(e);
339 }
340 
341 mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
342                                              QualType promotionTy) {
343   e = e->IgnoreParens();
344   if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
345     switch (bo->getOpcode()) {
346 #define HANDLE_BINOP(OP)                                                       \
347   case BO_##OP:                                                                \
348     return emitBin##OP(emitBinOps(bo, promotionTy));
349       HANDLE_BINOP(Add)
350       HANDLE_BINOP(Sub)
351 #undef HANDLE_BINOP
352     default:
353       break;
354     }
355   } else if (isa<UnaryOperator>(e)) {
356     cgf.cgm.errorNYI("emitPromoted UnaryOperator");
357     return {};
358   }
359 
360   mlir::Value result = Visit(const_cast<Expr *>(e));
361   if (!promotionTy.isNull())
362     cgf.cgm.errorNYI("emitPromoted emitPromotedValue");
363 
364   return result;
365 }
366 
367 mlir::Value
368 ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
369                                                QualType promotionTy) {
370   if (e->getType()->isAnyComplexType()) {
371     if (!promotionTy.isNull())
372       return cgf.emitPromotedComplexExpr(e, promotionTy);
373     return Visit(const_cast<Expr *>(e));
374   }
375 
376   cgf.cgm.errorNYI("emitPromotedComplexOperand non-complex type");
377   return {};
378 }
379 
380 ComplexExprEmitter::BinOpInfo
381 ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
382   BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};
383   binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);
384   binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);
385   binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;
386   binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
387   return binOpInfo;
388 }
389 
390 mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
391   assert(!cir::MissingFeatures::fastMathFlags());
392   assert(!cir::MissingFeatures::cgFPOptionsRAII());
393   return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs);
394 }
395 
396 mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
397   assert(!cir::MissingFeatures::fastMathFlags());
398   assert(!cir::MissingFeatures::cgFPOptionsRAII());
399   return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs);
400 }
401 
402 LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
403   assert(e->getOpcode() == BO_Assign && "Expected assign op");
404 
405   mlir::Value value; // ignored
406   LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
407   if (getLangOpts().OpenMP)
408     cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
409 
410   return lvalue;
411 }
412 
413 mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
414   assert(e && getComplexType(e->getType()) &&
415          "Invalid complex expression to emit");
416 
417   return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));
418 }
419 
420 void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
421                                         LValue dest, bool isInit) {
422   ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
423 }
424 
425 mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
426                                                     QualType promotionType) {
427   return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
428 }
429