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