1 //===-- Lower/ComplexExpr.h -- lowering of complex values -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef FORTRAN_LOWER_COMPLEXEXPR_H
10 #define FORTRAN_LOWER_COMPLEXEXPR_H
11 
12 #include "flang/Lower/FIRBuilder.h"
13 
14 namespace Fortran::lower {
15 
16 /// Helper to facilitate lowering of COMPLEX manipulations in FIR.
17 class ComplexExprHelper {
18 public:
ComplexExprHelper(FirOpBuilder & builder,mlir::Location loc)19   explicit ComplexExprHelper(FirOpBuilder &builder, mlir::Location loc)
20       : builder(builder), loc(loc) {}
21   ComplexExprHelper(const ComplexExprHelper &) = delete;
22 
23   // The values of part enum members are meaningful for
24   // InsertValueOp and ExtractValueOp so they are explicit.
25   enum class Part { Real = 0, Imag = 1 };
26 
27   /// Type helper. Determine the type. Do not create MLIR operations.
28   mlir::Type getComplexPartType(mlir::Value cplx);
29   mlir::Type getComplexPartType(mlir::Type complexType);
30 
31   /// Complex operation creation helper. They create MLIR operations.
32   mlir::Value createComplex(fir::KindTy kind, mlir::Value real,
33                             mlir::Value imag);
34 
35   /// Create a complex value.
36   mlir::Value createComplex(mlir::Type complexType, mlir::Value real,
37                             mlir::Value imag);
38 
extractComplexPart(mlir::Value cplx,bool isImagPart)39   mlir::Value extractComplexPart(mlir::Value cplx, bool isImagPart) {
40     return isImagPart ? extract<Part::Imag>(cplx) : extract<Part::Real>(cplx);
41   }
42 
43   /// Returns (Real, Imag) pair of \p cplx
extractParts(mlir::Value cplx)44   std::pair<mlir::Value, mlir::Value> extractParts(mlir::Value cplx) {
45     return {extract<Part::Real>(cplx), extract<Part::Imag>(cplx)};
46   }
47 
insertComplexPart(mlir::Value cplx,mlir::Value part,bool isImagPart)48   mlir::Value insertComplexPart(mlir::Value cplx, mlir::Value part,
49                                 bool isImagPart) {
50     return isImagPart ? insert<Part::Imag>(cplx, part)
51                       : insert<Part::Real>(cplx, part);
52   }
53 
54   mlir::Value createComplexCompare(mlir::Value cplx1, mlir::Value cplx2,
55                                    bool eq);
56 
57 protected:
58   template <Part partId>
extract(mlir::Value cplx)59   mlir::Value extract(mlir::Value cplx) {
60     return builder.create<fir::ExtractValueOp>(loc, getComplexPartType(cplx),
61                                                cplx, createPartId<partId>());
62   }
63 
64   template <Part partId>
insert(mlir::Value cplx,mlir::Value part)65   mlir::Value insert(mlir::Value cplx, mlir::Value part) {
66     return builder.create<fir::InsertValueOp>(loc, cplx.getType(), cplx, part,
67                                               createPartId<partId>());
68   }
69 
70   template <Part partId>
createPartId()71   mlir::Value createPartId() {
72     return builder.createIntegerConstant(loc, builder.getIndexType(),
73                                          static_cast<int>(partId));
74   }
75 
76 private:
77   FirOpBuilder &builder;
78   mlir::Location loc;
79 };
80 
81 } // namespace Fortran::lower
82 
83 #endif // FORTRAN_LOWER_COMPLEXEXPR_H
84