1 //===-- ConvertExpr.cpp ---------------------------------------------------===// 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 #include "flang/Lower/ConvertExpr.h" 14 #include "flang/Evaluate/fold.h" 15 #include "flang/Evaluate/real.h" 16 #include "flang/Evaluate/traverse.h" 17 #include "flang/Lower/AbstractConverter.h" 18 #include "flang/Lower/Todo.h" 19 #include "flang/Semantics/expression.h" 20 #include "flang/Semantics/symbol.h" 21 #include "flang/Semantics/tools.h" 22 #include "flang/Semantics/type.h" 23 #include "mlir/Dialect/StandardOps/IR/Ops.h" 24 #include "llvm/Support/Debug.h" 25 26 #define DEBUG_TYPE "flang-lower-expr" 27 28 //===----------------------------------------------------------------------===// 29 // The composition and structure of Fortran::evaluate::Expr is defined in 30 // the various header files in include/flang/Evaluate. You are referred 31 // there for more information on these data structures. Generally speaking, 32 // these data structures are a strongly typed family of abstract data types 33 // that, composed as trees, describe the syntax of Fortran expressions. 34 // 35 // This part of the bridge can traverse these tree structures and lower them 36 // to the correct FIR representation in SSA form. 37 //===----------------------------------------------------------------------===// 38 39 namespace { 40 41 /// Lowering of Fortran::evaluate::Expr<T> expressions 42 class ScalarExprLowering { 43 public: 44 using ExtValue = fir::ExtendedValue; 45 46 explicit ScalarExprLowering(mlir::Location loc, 47 Fortran::lower::AbstractConverter &converter, 48 Fortran::lower::SymMap &symMap) 49 : location{loc}, converter{converter}, 50 builder{converter.getFirOpBuilder()}, symMap{symMap} {} 51 52 mlir::Location getLoc() { return location; } 53 54 /// Generate an integral constant of `value` 55 template <int KIND> 56 mlir::Value genIntegerConstant(mlir::MLIRContext *context, 57 std::int64_t value) { 58 mlir::Type type = 59 converter.genType(Fortran::common::TypeCategory::Integer, KIND); 60 return builder.createIntegerConstant(getLoc(), type, value); 61 } 62 63 ExtValue genval(Fortran::semantics::SymbolRef sym) { 64 TODO(getLoc(), "genval SymbolRef"); 65 } 66 67 ExtValue genval(const Fortran::evaluate::BOZLiteralConstant &) { 68 TODO(getLoc(), "genval BOZ"); 69 } 70 71 /// Return indirection to function designated in ProcedureDesignator. 72 /// The type of the function indirection is not guaranteed to match the one 73 /// of the ProcedureDesignator due to Fortran implicit typing rules. 74 ExtValue genval(const Fortran::evaluate::ProcedureDesignator &proc) { 75 TODO(getLoc(), "genval ProcedureDesignator"); 76 } 77 78 ExtValue genval(const Fortran::evaluate::NullPointer &) { 79 TODO(getLoc(), "genval NullPointer"); 80 } 81 82 ExtValue genval(const Fortran::evaluate::StructureConstructor &ctor) { 83 TODO(getLoc(), "genval StructureConstructor"); 84 } 85 86 /// Lowering of an <i>ac-do-variable</i>, which is not a Symbol. 87 ExtValue genval(const Fortran::evaluate::ImpliedDoIndex &var) { 88 TODO(getLoc(), "genval ImpliedDoIndex"); 89 } 90 91 ExtValue genval(const Fortran::evaluate::DescriptorInquiry &desc) { 92 TODO(getLoc(), "genval DescriptorInquiry"); 93 } 94 95 ExtValue genval(const Fortran::evaluate::TypeParamInquiry &) { 96 TODO(getLoc(), "genval TypeParamInquiry"); 97 } 98 99 template <int KIND> 100 ExtValue genval(const Fortran::evaluate::ComplexComponent<KIND> &part) { 101 TODO(getLoc(), "genval ComplexComponent"); 102 } 103 104 template <int KIND> 105 ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type< 106 Fortran::common::TypeCategory::Integer, KIND>> &op) { 107 TODO(getLoc(), "genval Negate integer"); 108 } 109 110 template <int KIND> 111 ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type< 112 Fortran::common::TypeCategory::Real, KIND>> &op) { 113 TODO(getLoc(), "genval Negate real"); 114 } 115 template <int KIND> 116 ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type< 117 Fortran::common::TypeCategory::Complex, KIND>> &op) { 118 TODO(getLoc(), "genval Negate complex"); 119 } 120 121 #undef GENBIN 122 #define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp) \ 123 template <int KIND> \ 124 ExtValue genval(const Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type< \ 125 Fortran::common::TypeCategory::GenBinTyCat, KIND>> &x) { \ 126 TODO(getLoc(), "genval GenBinEvOp"); \ 127 } 128 129 GENBIN(Add, Integer, mlir::arith::AddIOp) 130 GENBIN(Add, Real, mlir::arith::AddFOp) 131 GENBIN(Add, Complex, fir::AddcOp) 132 GENBIN(Subtract, Integer, mlir::arith::SubIOp) 133 GENBIN(Subtract, Real, mlir::arith::SubFOp) 134 GENBIN(Subtract, Complex, fir::SubcOp) 135 GENBIN(Multiply, Integer, mlir::arith::MulIOp) 136 GENBIN(Multiply, Real, mlir::arith::MulFOp) 137 GENBIN(Multiply, Complex, fir::MulcOp) 138 GENBIN(Divide, Integer, mlir::arith::DivSIOp) 139 GENBIN(Divide, Real, mlir::arith::DivFOp) 140 GENBIN(Divide, Complex, fir::DivcOp) 141 142 template <Fortran::common::TypeCategory TC, int KIND> 143 ExtValue genval( 144 const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &op) { 145 TODO(getLoc(), "genval Power"); 146 } 147 148 template <Fortran::common::TypeCategory TC, int KIND> 149 ExtValue genval( 150 const Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>> 151 &op) { 152 TODO(getLoc(), "genval RealToInt"); 153 } 154 155 template <int KIND> 156 ExtValue genval(const Fortran::evaluate::ComplexConstructor<KIND> &op) { 157 TODO(getLoc(), "genval ComplexConstructor"); 158 } 159 160 template <int KIND> 161 ExtValue genval(const Fortran::evaluate::Concat<KIND> &op) { 162 TODO(getLoc(), "genval Concat<KIND>"); 163 } 164 165 /// MIN and MAX operations 166 template <Fortran::common::TypeCategory TC, int KIND> 167 ExtValue 168 genval(const Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>> 169 &op) { 170 TODO(getLoc(), "genval Extremum<TC, KIND>"); 171 } 172 173 template <int KIND> 174 ExtValue genval(const Fortran::evaluate::SetLength<KIND> &x) { 175 TODO(getLoc(), "genval SetLength<KIND>"); 176 } 177 178 template <int KIND> 179 ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< 180 Fortran::common::TypeCategory::Integer, KIND>> &op) { 181 TODO(getLoc(), "genval integer comparison"); 182 } 183 template <int KIND> 184 ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< 185 Fortran::common::TypeCategory::Real, KIND>> &op) { 186 TODO(getLoc(), "genval real comparison"); 187 } 188 template <int KIND> 189 ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< 190 Fortran::common::TypeCategory::Complex, KIND>> &op) { 191 TODO(getLoc(), "genval complex comparison"); 192 } 193 template <int KIND> 194 ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< 195 Fortran::common::TypeCategory::Character, KIND>> &op) { 196 TODO(getLoc(), "genval char comparison"); 197 } 198 199 ExtValue 200 genval(const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &op) { 201 TODO(getLoc(), "genval comparison"); 202 } 203 204 template <Fortran::common::TypeCategory TC1, int KIND, 205 Fortran::common::TypeCategory TC2> 206 ExtValue 207 genval(const Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>, 208 TC2> &convert) { 209 TODO(getLoc(), "genval convert<TC1, KIND, TC2>"); 210 } 211 212 template <typename A> 213 ExtValue genval(const Fortran::evaluate::Parentheses<A> &op) { 214 TODO(getLoc(), "genval parentheses<A>"); 215 } 216 217 template <int KIND> 218 ExtValue genval(const Fortran::evaluate::Not<KIND> &op) { 219 TODO(getLoc(), "genval Not<KIND>"); 220 } 221 222 template <int KIND> 223 ExtValue genval(const Fortran::evaluate::LogicalOperation<KIND> &op) { 224 TODO(getLoc(), "genval LogicalOperation<KIND>"); 225 } 226 227 /// Convert a scalar literal constant to IR. 228 template <Fortran::common::TypeCategory TC, int KIND> 229 ExtValue genScalarLit( 230 const Fortran::evaluate::Scalar<Fortran::evaluate::Type<TC, KIND>> 231 &value) { 232 if constexpr (TC == Fortran::common::TypeCategory::Integer) { 233 return genIntegerConstant<KIND>(builder.getContext(), value.ToInt64()); 234 } else if constexpr (TC == Fortran::common::TypeCategory::Logical) { 235 TODO(getLoc(), "genval bool constant"); 236 } else if constexpr (TC == Fortran::common::TypeCategory::Real) { 237 TODO(getLoc(), "genval real constant"); 238 } else if constexpr (TC == Fortran::common::TypeCategory::Complex) { 239 TODO(getLoc(), "genval complex constant"); 240 } else /*constexpr*/ { 241 llvm_unreachable("unhandled constant"); 242 } 243 } 244 245 template <Fortran::common::TypeCategory TC, int KIND> 246 ExtValue 247 genval(const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>> 248 &con) { 249 if (con.Rank() > 0) 250 TODO(getLoc(), "genval array constant"); 251 std::optional<Fortran::evaluate::Scalar<Fortran::evaluate::Type<TC, KIND>>> 252 opt = con.GetScalarValue(); 253 assert(opt.has_value() && "constant has no value"); 254 if constexpr (TC == Fortran::common::TypeCategory::Character) { 255 TODO(getLoc(), "genval char constant"); 256 } else { 257 return genScalarLit<TC, KIND>(opt.value()); 258 } 259 } 260 261 fir::ExtendedValue genval( 262 const Fortran::evaluate::Constant<Fortran::evaluate::SomeDerived> &con) { 263 TODO(getLoc(), "genval constant derived"); 264 } 265 266 template <typename A> 267 ExtValue genval(const Fortran::evaluate::ArrayConstructor<A> &) { 268 TODO(getLoc(), "genval ArrayConstructor<A>"); 269 } 270 271 ExtValue genval(const Fortran::evaluate::ComplexPart &x) { 272 TODO(getLoc(), "genval ComplexPart"); 273 } 274 275 ExtValue genval(const Fortran::evaluate::Substring &ss) { 276 TODO(getLoc(), "genval Substring"); 277 } 278 279 ExtValue genval(const Fortran::evaluate::Subscript &subs) { 280 TODO(getLoc(), "genval Subscript"); 281 } 282 283 ExtValue genval(const Fortran::evaluate::DataRef &dref) { 284 TODO(getLoc(), "genval DataRef"); 285 } 286 287 ExtValue genval(const Fortran::evaluate::Component &cmpt) { 288 TODO(getLoc(), "genval Component"); 289 } 290 291 ExtValue genval(const Fortran::semantics::Bound &bound) { 292 TODO(getLoc(), "genval Bound"); 293 } 294 295 ExtValue genval(const Fortran::evaluate::ArrayRef &aref) { 296 TODO(getLoc(), "genval ArrayRef"); 297 } 298 299 ExtValue genval(const Fortran::evaluate::CoarrayRef &coref) { 300 TODO(getLoc(), "genval CoarrayRef"); 301 } 302 303 template <typename A> 304 ExtValue genval(const Fortran::evaluate::Designator<A> &des) { 305 TODO(getLoc(), "genval Designator<A>"); 306 } 307 308 template <typename A> 309 ExtValue genval(const Fortran::evaluate::FunctionRef<A> &funcRef) { 310 TODO(getLoc(), "genval FunctionRef<A>"); 311 } 312 313 ExtValue genval(const Fortran::evaluate::ProcedureRef &procRef) { 314 TODO(getLoc(), "genval ProcedureRef"); 315 } 316 317 template <typename A> 318 bool isScalar(const A &x) { 319 return x.Rank() == 0; 320 } 321 322 template <typename A> 323 ExtValue genval(const Fortran::evaluate::Expr<A> &x) { 324 if (isScalar(x)) 325 return std::visit([&](const auto &e) { return genval(e); }, x.u); 326 TODO(getLoc(), "genval Expr<A> arrays"); 327 } 328 329 template <int KIND> 330 ExtValue genval(const Fortran::evaluate::Expr<Fortran::evaluate::Type< 331 Fortran::common::TypeCategory::Logical, KIND>> &exp) { 332 return std::visit([&](const auto &e) { return genval(e); }, exp.u); 333 } 334 335 private: 336 mlir::Location location; 337 Fortran::lower::AbstractConverter &converter; 338 fir::FirOpBuilder &builder; 339 Fortran::lower::SymMap &symMap; 340 }; 341 } // namespace 342 343 fir::ExtendedValue Fortran::lower::createSomeExtendedExpression( 344 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 345 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap) { 346 LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "expr: ") << '\n'); 347 return ScalarExprLowering{loc, converter, symMap}.genval(expr); 348 } 349