1 //===-- Complex.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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef FORTRAN_OPTIMIZER_BUILDER_COMPLEX_H
14 #define FORTRAN_OPTIMIZER_BUILDER_COMPLEX_H
15 
16 #include "flang/Optimizer/Builder/FIRBuilder.h"
17 
18 namespace fir::factory {
19 
20 /// Helper to facilitate lowering of COMPLEX manipulations in FIR.
21 class Complex {
22 public:
Complex(FirOpBuilder & builder,mlir::Location loc)23   explicit Complex(FirOpBuilder &builder, mlir::Location loc)
24       : builder(builder), loc(loc) {}
25   Complex(const Complex &) = delete;
26 
27   // The values of part enum members are meaningful for
28   // InsertValueOp and ExtractValueOp so they are explicit.
29   enum class Part { Real = 0, Imag = 1 };
30 
31   /// Get the Complex Type. Determine the type. Do not create MLIR operations.
32   mlir::Type getComplexPartType(mlir::Value cplx) const;
33   mlir::Type getComplexPartType(mlir::Type complexType) const;
34 
35   /// Complex operation creation. They create MLIR operations.
36   mlir::Value createComplex(fir::KindTy kind, mlir::Value real,
37                             mlir::Value imag);
38 
39   /// Create a complex value.
40   mlir::Value createComplex(mlir::Type complexType, mlir::Value real,
41                             mlir::Value imag);
42 
43   /// Returns the Real/Imag part of \p cplx
extractComplexPart(mlir::Value cplx,bool isImagPart)44   mlir::Value extractComplexPart(mlir::Value cplx, bool isImagPart) {
45     return isImagPart ? extract<Part::Imag>(cplx) : extract<Part::Real>(cplx);
46   }
47 
48   /// Returns (Real, Imag) pair of \p cplx
extractParts(mlir::Value cplx)49   std::pair<mlir::Value, mlir::Value> extractParts(mlir::Value cplx) {
50     return {extract<Part::Real>(cplx), extract<Part::Imag>(cplx)};
51   }
52 
insertComplexPart(mlir::Value cplx,mlir::Value part,bool isImagPart)53   mlir::Value insertComplexPart(mlir::Value cplx, mlir::Value part,
54                                 bool isImagPart) {
55     return isImagPart ? insert<Part::Imag>(cplx, part)
56                       : insert<Part::Real>(cplx, part);
57   }
58 
59 protected:
60   template <Part partId>
extract(mlir::Value cplx)61   mlir::Value extract(mlir::Value cplx) {
62     return builder.create<fir::ExtractValueOp>(
63         loc, getComplexPartType(cplx), cplx,
64         builder.getArrayAttr({builder.getIntegerAttr(
65             builder.getIndexType(), static_cast<int>(partId))}));
66   }
67 
68   template <Part partId>
insert(mlir::Value cplx,mlir::Value part)69   mlir::Value insert(mlir::Value cplx, mlir::Value part) {
70     return builder.create<fir::InsertValueOp>(
71         loc, cplx.getType(), cplx, part,
72         builder.getArrayAttr({builder.getIntegerAttr(
73             builder.getIndexType(), static_cast<int>(partId))}));
74   }
75 
76   template <Part partId>
createPartId()77   mlir::Value createPartId() {
78     return builder.createIntegerConstant(loc, builder.getIndexType(),
79                                          static_cast<int>(partId));
80   }
81 
82 private:
83   FirOpBuilder &builder;
84   mlir::Location loc;
85 };
86 
87 } // namespace fir::factory
88 
89 #endif // FORTRAN_OPTIMIZER_BUILDER_COMPLEX_H
90