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