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