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:
ComplexExprEmitter(CIRGenFunction & cgf)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.
emitLoadOfLValue(const Expr * e)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
getPromotionType(QualType ty,bool isDivOpCode=false)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
getComplexType(QualType type)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
emitBinAssignLValue(const BinaryOperator * e,mlir::Value & value)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
emitCast(CastKind ck,Expr * op,QualType destTy)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
emitConstant(const CIRGenFunction::ConstantEmission & constant,Expr * e)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
emitLoadOfLValue(LValue lv,SourceLocation loc)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
emitStoreOfComplex(mlir::Location loc,mlir::Value val,LValue lv,bool isInit)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
VisitAbstractConditionalOperator(const AbstractConditionalOperator * e)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
VisitArraySubscriptExpr(Expr * e)205 mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) {
206 return emitLoadOfLValue(e);
207 }
208
VisitBinAssign(const BinaryOperator * e)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
VisitBinComma(const BinaryOperator * e)225 mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
226 cgf.emitIgnoredExpr(e->getLHS());
227 return Visit(e->getRHS());
228 }
229
VisitCallExpr(const CallExpr * e)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
VisitCastExpr(CastExpr * e)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
VisitChooseExpr(ChooseExpr * e)252 mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {
253 return Visit(e->getChosenSubExpr());
254 }
255
256 mlir::Value
VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr * e)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
VisitDeclRefExpr(DeclRefExpr * e)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
VisitGenericSelectionExpr(GenericSelectionExpr * e)270 ComplexExprEmitter::VisitGenericSelectionExpr(GenericSelectionExpr *e) {
271 return Visit(e->getResultExpr());
272 }
273
VisitImplicitCastExpr(ImplicitCastExpr * e)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
VisitInitListExpr(const InitListExpr * e)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
VisitImaginaryLiteral(const ImaginaryLiteral * il)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
VisitParenExpr(ParenExpr * e)328 mlir::Value ComplexExprEmitter::VisitParenExpr(ParenExpr *e) {
329 return Visit(e->getSubExpr());
330 }
331
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr * e)332 mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr(
333 SubstNonTypeTemplateParmExpr *e) {
334 return Visit(e->getReplacement());
335 }
336
VisitUnaryDeref(const Expr * e)337 mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {
338 return emitLoadOfLValue(e);
339 }
340
emitPromoted(const Expr * e,QualType promotionTy)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
emitPromotedComplexOperand(const Expr * e,QualType promotionTy)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
emitBinOps(const BinaryOperator * e,QualType promotionTy)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
emitBinAdd(const BinOpInfo & op)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
emitBinSub(const BinOpInfo & op)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
emitComplexAssignmentLValue(const BinaryOperator * e)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
emitComplexExpr(const Expr * e)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
emitStoreOfComplex(mlir::Location loc,mlir::Value v,LValue dest,bool isInit)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
emitPromotedComplexExpr(const Expr * e,QualType promotionType)425 mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
426 QualType promotionType) {
427 return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
428 }
429