• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Lower/Support/BoxValue.h -- internal box 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 LOWER_SUPPORT_BOXVALUE_H
10 #define LOWER_SUPPORT_BOXVALUE_H
11 
12 #include "mlir/IR/Value.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/Support/Compiler.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <utility>
17 #include <variant>
18 
19 namespace fir {
20 class CharBoxValue;
21 class ArrayBoxValue;
22 class CharArrayBoxValue;
23 class BoxValue;
24 class ProcBoxValue;
25 
26 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CharBoxValue &);
27 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ArrayBoxValue &);
28 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CharArrayBoxValue &);
29 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const BoxValue &);
30 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ProcBoxValue &);
31 
32 //===----------------------------------------------------------------------===//
33 //
34 // Boxed values
35 //
36 // Define a set of containers used internally by the lowering bridge to keep
37 // track of extended values associated with a Fortran subexpression. These
38 // associations are maintained during the construction of FIR.
39 //
40 //===----------------------------------------------------------------------===//
41 
42 /// Most expressions of intrinsic type can be passed unboxed. Their properties
43 /// are known statically.
44 using UnboxedValue = mlir::Value;
45 
46 /// Abstract base class.
47 class AbstractBox {
48 public:
49   AbstractBox() = delete;
AbstractBox(mlir::Value addr)50   AbstractBox(mlir::Value addr) : addr{addr} {}
getAddr()51   mlir::Value getAddr() const { return addr; }
52 
53 protected:
54   mlir::Value addr;
55 };
56 
57 /// Expressions of CHARACTER type have an associated, possibly dynamic LEN
58 /// value.
59 class CharBoxValue : public AbstractBox {
60 public:
CharBoxValue(mlir::Value addr,mlir::Value len)61   CharBoxValue(mlir::Value addr, mlir::Value len)
62       : AbstractBox{addr}, len{len} {}
63 
clone(mlir::Value newBase)64   CharBoxValue clone(mlir::Value newBase) const { return {newBase, len}; }
65 
getLen()66   mlir::Value getLen() const { return len; }
getBuffer()67   mlir::Value getBuffer() const { return getAddr(); }
68 
69   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
70                                        const CharBoxValue &);
dump()71   LLVM_DUMP_METHOD void dump() const { llvm::errs() << *this; }
72 
73 protected:
74   mlir::Value len;
75 };
76 
77 /// Abstract base class.
78 /// Expressions of type array have at minimum a shape. These expressions may
79 /// have lbound attributes (dynamic values) that affect the interpretation of
80 /// indexing expressions.
81 class AbstractArrayBox {
82 public:
83   AbstractArrayBox() = default;
AbstractArrayBox(llvm::ArrayRef<mlir::Value> extents,llvm::ArrayRef<mlir::Value> lbounds)84   AbstractArrayBox(llvm::ArrayRef<mlir::Value> extents,
85                    llvm::ArrayRef<mlir::Value> lbounds)
86       : extents{extents.begin(), extents.end()}, lbounds{lbounds.begin(),
87                                                          lbounds.end()} {}
88 
89   // Every array has extents that describe its shape.
getExtents()90   const llvm::SmallVectorImpl<mlir::Value> &getExtents() const {
91     return extents;
92   }
93 
94   // An array expression may have user-defined lower bound values.
95   // If this vector is empty, the default in all dimensions in `1`.
getLBounds()96   const llvm::SmallVectorImpl<mlir::Value> &getLBounds() const {
97     return lbounds;
98   }
99 
lboundsAllOne()100   bool lboundsAllOne() const { return lbounds.empty(); }
101 
102 protected:
103   llvm::SmallVector<mlir::Value, 4> extents;
104   llvm::SmallVector<mlir::Value, 4> lbounds;
105 };
106 
107 /// Expressions with rank > 0 have extents. They may also have lbounds that are
108 /// not 1.
109 class ArrayBoxValue : public AbstractBox, public AbstractArrayBox {
110 public:
111   ArrayBoxValue(mlir::Value addr, llvm::ArrayRef<mlir::Value> extents,
112                 llvm::ArrayRef<mlir::Value> lbounds = {})
113       : AbstractBox{addr}, AbstractArrayBox{extents, lbounds} {}
114 
clone(mlir::Value newBase)115   ArrayBoxValue clone(mlir::Value newBase) const {
116     return {newBase, extents, lbounds};
117   }
118 
119   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
120                                        const ArrayBoxValue &);
dump()121   LLVM_DUMP_METHOD void dump() const { operator<<(llvm::errs(), *this); }
122 };
123 
124 /// Expressions of type CHARACTER and with rank > 0.
125 class CharArrayBoxValue : public CharBoxValue, public AbstractArrayBox {
126 public:
127   CharArrayBoxValue(mlir::Value addr, mlir::Value len,
128                     llvm::ArrayRef<mlir::Value> extents,
129                     llvm::ArrayRef<mlir::Value> lbounds = {})
130       : CharBoxValue{addr, len}, AbstractArrayBox{extents, lbounds} {}
131 
clone(mlir::Value newBase)132   CharArrayBoxValue clone(mlir::Value newBase) const {
133     return {newBase, len, extents, lbounds};
134   }
135 
136   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
137                                        const CharArrayBoxValue &);
dump()138   LLVM_DUMP_METHOD void dump() const { operator<<(llvm::errs(), *this); }
139 };
140 
141 /// Expressions that are procedure POINTERs may need a set of references to
142 /// variables in the host scope.
143 class ProcBoxValue : public AbstractBox {
144 public:
ProcBoxValue(mlir::Value addr,mlir::Value context)145   ProcBoxValue(mlir::Value addr, mlir::Value context)
146       : AbstractBox{addr}, hostContext{context} {}
147 
clone(mlir::Value newBase)148   ProcBoxValue clone(mlir::Value newBase) const {
149     return {newBase, hostContext};
150   }
151 
getHostContext()152   mlir::Value getHostContext() const { return hostContext; }
153 
154   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
155                                        const ProcBoxValue &);
dump()156   LLVM_DUMP_METHOD void dump() const { operator<<(llvm::errs(), *this); }
157 
158 protected:
159   mlir::Value hostContext;
160 };
161 
162 /// In the generalized form, a boxed value can have a dynamic size, be an array
163 /// with dynamic extents and lbounds, and take dynamic type parameters.
164 class BoxValue : public AbstractBox, public AbstractArrayBox {
165 public:
BoxValue(mlir::Value addr)166   BoxValue(mlir::Value addr) : AbstractBox{addr}, AbstractArrayBox{} {}
BoxValue(mlir::Value addr,mlir::Value len)167   BoxValue(mlir::Value addr, mlir::Value len)
168       : AbstractBox{addr}, AbstractArrayBox{}, len{len} {}
169   BoxValue(mlir::Value addr, llvm::ArrayRef<mlir::Value> extents,
170            llvm::ArrayRef<mlir::Value> lbounds = {})
171       : AbstractBox{addr}, AbstractArrayBox{extents, lbounds} {}
172   BoxValue(mlir::Value addr, mlir::Value len,
173            llvm::ArrayRef<mlir::Value> params,
174            llvm::ArrayRef<mlir::Value> extents,
175            llvm::ArrayRef<mlir::Value> lbounds = {})
176       : AbstractBox{addr}, AbstractArrayBox{extents, lbounds}, len{len},
177         params{params.begin(), params.end()} {}
178 
clone(mlir::Value newBase)179   BoxValue clone(mlir::Value newBase) const {
180     return {newBase, len, params, extents, lbounds};
181   }
182 
getLen()183   mlir::Value getLen() const { return len; }
getLenTypeParams()184   const llvm::SmallVectorImpl<mlir::Value> &getLenTypeParams() const {
185     return params;
186   }
187 
188   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const BoxValue &);
dump()189   LLVM_DUMP_METHOD void dump() const { operator<<(llvm::errs(), *this); }
190 
191 protected:
192   mlir::Value len;
193   llvm::SmallVector<mlir::Value, 2> params;
194 };
195 
196 /// Used for triple notation (array slices)
197 using RangeBoxValue = std::tuple<mlir::Value, mlir::Value, mlir::Value>;
198 
199 class ExtendedValue;
200 
201 mlir::Value getBase(const ExtendedValue &exv);
202 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ExtendedValue &);
203 ExtendedValue substBase(const ExtendedValue &exv, mlir::Value base);
204 
205 /// An extended value is a box of values pertaining to a discrete entity. It is
206 /// used in lowering to track all the runtime values related to an entity. For
207 /// example, an entity may have an address in memory that contains its value(s)
208 /// as well as various attribute values that describe the shape and starting
209 /// indices if it is an array entity.
210 class ExtendedValue {
211 public:
212   template <typename A>
ExtendedValue(A && box)213   constexpr ExtendedValue(A &&box) : box{std::forward<A>(box)} {}
214 
getCharBox()215   constexpr const CharBoxValue *getCharBox() const {
216     return std::get_if<CharBoxValue>(&box);
217   }
218 
getUnboxed()219   constexpr const UnboxedValue *getUnboxed() const {
220     return std::get_if<UnboxedValue>(&box);
221   }
222 
223   /// LLVM style debugging of extended values
dump()224   LLVM_DUMP_METHOD void dump() const { llvm::errs() << *this << '\n'; }
225 
226   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
227                                        const ExtendedValue &);
228   friend mlir::Value getBase(const ExtendedValue &exv);
229   friend ExtendedValue substBase(const ExtendedValue &exv, mlir::Value base);
230 
231 private:
232   std::variant<UnboxedValue, CharBoxValue, ArrayBoxValue, CharArrayBoxValue,
233                BoxValue, ProcBoxValue>
234       box;
235 };
236 } // namespace fir
237 
238 #endif // LOWER_SUPPORT_BOXVALUE_H
239