1#include "CIRGenBuilder.h"
2#include "CIRGenFunction.h"
3
4#include "clang/AST/StmtVisitor.h"
5
6using namespace clang;
7using namespace clang::CIRGen;
8
9namespace {
10class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
11 CIRGenFunction &cgf;
12 CIRGenBuilderTy &builder;
13
14public:
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(feature: "HigherPrecisionTypeForComplexArithmetic");
86 return QualType();
87 }
88
89 if (elementTy.UseExcessPrecision(Ctx: cgf.getContext()))
90 return cgf.getContext().getComplexType(T: cgf.getContext().FloatTy);
91 }
92
93 if (ty.UseExcessPrecision(Ctx: 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
114static const ComplexType *getComplexType(QualType type) {
115 type = type.getCanonicalType();
116 if (const ComplexType *comp = dyn_cast<ComplexType>(Val&: type))
117 return comp;
118 return cast<ComplexType>(Val: cast<AtomicType>(Val&: type)->getValueType());
119}
120
121LValue 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: 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
138mlir::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(feature: "ComplexType Cast");
148 return {};
149}
150
151mlir::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
162mlir::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
172void 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
184mlir::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
205mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) {
206 return emitLoadOfLValue(e);
207}
208
209mlir::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
225mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
226 cgf.emitIgnoredExpr(e: e->getLHS());
227 return Visit(e->getRHS());
228}
229
230mlir::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
237mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) {
238 if (const auto *ece = dyn_cast<ExplicitCastExpr>(Val: e)) {
239 // Bind VLAs in the cast type.
240 if (ece->getType()->isVariablyModifiedType()) {
241 cgf.cgm.errorNYI(feature: "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
252mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
253 return Visit(e->getChosenSubExpr());
254}
255
256mlir::Value
257ComplexExprEmitter::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
263mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {
264 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
265 return emitConstant(constant, e);
266 return emitLoadOfLValue(e);
267}
268
269mlir::Value
270ComplexExprEmitter::VisitGenericSelectionExpr(GenericSelectionExpr *e) {
271 return Visit(e->getResultExpr());
272}
273
274mlir::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
282mlir::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(Init: 0));
286 mlir::Value imag = cgf.emitScalarExpr(e->getInit(Init: 1));
287 return builder.createComplexCreate(loc, real, imag);
288 }
289
290 if (e->getNumInits() == 1) {
291 cgf.cgm.errorNYI(feature: "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
300mlir::Value
301ComplexExprEmitter::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>(Val: 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>(Val: 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
328mlir::Value ComplexExprEmitter::VisitParenExpr(ParenExpr *e) {
329 return Visit(e->getSubExpr());
330}
331
332mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr(
333 SubstNonTypeTemplateParmExpr *e) {
334 return Visit(e->getReplacement());
335}
336
337mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {
338 return emitLoadOfLValue(e);
339}
340
341mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
342 QualType promotionTy) {
343 e = e->IgnoreParens();
344 if (const auto *bo = dyn_cast<BinaryOperator>(Val: 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>(Val: e)) {
356 cgf.cgm.errorNYI(feature: "emitPromoted UnaryOperator");
357 return {};
358 }
359
360 mlir::Value result = Visit(const_cast<Expr *>(e));
361 if (!promotionTy.isNull())
362 cgf.cgm.errorNYI(feature: "emitPromoted emitPromotedValue");
363
364 return result;
365}
366
367mlir::Value
368ComplexExprEmitter::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(feature: "emitPromotedComplexOperand non-complex type");
377 return {};
378}
379
380ComplexExprEmitter::BinOpInfo
381ComplexExprEmitter::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(LO: cgf.getLangOpts());
387 return binOpInfo;
388}
389
390mlir::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
396mlir::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
402LValue 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(feature: "emitComplexAssignmentLValue OpenMP");
409
410 return lvalue;
411}
412
413mlir::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
420void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
421 LValue dest, bool isInit) {
422 ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
423}
424
425mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
426 QualType promotionType) {
427 return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
428}
429

source code of clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp