1 //===-- Lower/Support/Utils.h -- utilities ----------------------*- 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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef FORTRAN_LOWER_SUPPORT_UTILS_H
14 #define FORTRAN_LOWER_SUPPORT_UTILS_H
15 
16 #include "flang/Common/indirection.h"
17 #include "flang/Parser/char-block.h"
18 #include "flang/Semantics/tools.h"
19 #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
20 #include "mlir/Dialect/Func/IR/FuncOps.h"
21 #include "mlir/IR/BuiltinAttributes.h"
22 #include "llvm/ADT/StringRef.h"
23 #include <cstdint>
24 
25 namespace Fortran::lower {
26 using SomeExpr = Fortran::evaluate::Expr<Fortran::evaluate::SomeType>;
27 }
28 
29 //===----------------------------------------------------------------------===//
30 // Small inline helper functions to deal with repetitive, clumsy conversions.
31 //===----------------------------------------------------------------------===//
32 
33 /// Convert an F18 CharBlock to an LLVM StringRef.
toStringRef(const Fortran::parser::CharBlock & cb)34 inline llvm::StringRef toStringRef(const Fortran::parser::CharBlock &cb) {
35   return {cb.begin(), cb.size()};
36 }
37 
38 namespace fir {
39 /// Return the integer value of a arith::ConstantOp.
toInt(mlir::arith::ConstantOp cop)40 inline std::int64_t toInt(mlir::arith::ConstantOp cop) {
41   return cop.getValue().cast<mlir::IntegerAttr>().getValue().getSExtValue();
42 }
43 } // namespace fir
44 
45 /// Template helper to remove Fortran::common::Indirection wrappers.
46 template <typename A>
removeIndirection(const A & a)47 const A &removeIndirection(const A &a) {
48   return a;
49 }
50 template <typename A>
removeIndirection(const Fortran::common::Indirection<A> & a)51 const A &removeIndirection(const Fortran::common::Indirection<A> &a) {
52   return a.value();
53 }
54 
55 /// Clone subexpression and wrap it as a generic `Fortran::evaluate::Expr`.
56 template <typename A>
toEvExpr(const A & x)57 static Fortran::lower::SomeExpr toEvExpr(const A &x) {
58   return Fortran::evaluate::AsGenericExpr(Fortran::common::Clone(x));
59 }
60 
61 template <Fortran::common::TypeCategory FROM>
ignoreEvConvert(const Fortran::evaluate::Convert<Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,8>,FROM> & x)62 static Fortran::lower::SomeExpr ignoreEvConvert(
63     const Fortran::evaluate::Convert<
64         Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, 8>,
65         FROM> &x) {
66   return toEvExpr(x.left());
67 }
68 template <typename A>
ignoreEvConvert(const A & x)69 static Fortran::lower::SomeExpr ignoreEvConvert(const A &x) {
70   return toEvExpr(x);
71 }
72 
73 /// A vector subscript expression may be wrapped with a cast to INTEGER*8.
74 /// Get rid of it here so the vector can be loaded. Add it back when
75 /// generating the elemental evaluation (inside the loop nest).
76 inline Fortran::lower::SomeExpr
ignoreEvConvert(const Fortran::evaluate::Expr<Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,8>> & x)77 ignoreEvConvert(const Fortran::evaluate::Expr<Fortran::evaluate::Type<
78                     Fortran::common::TypeCategory::Integer, 8>> &x) {
79   return std::visit([](const auto &v) { return ignoreEvConvert(v); }, x.u);
80 }
81 
82 /// Zip two containers of the same size together and flatten the pairs. `flatZip
83 /// [1;2] [3;4]` yields `[1;3;2;4]`.
84 template <typename A>
flatZip(const A & container1,const A & container2)85 A flatZip(const A &container1, const A &container2) {
86   assert(container1.size() == container2.size());
87   A result;
88   for (auto [e1, e2] : llvm::zip(container1, container2)) {
89     result.emplace_back(e1);
90     result.emplace_back(e2);
91   }
92   return result;
93 }
94 
95 #endif // FORTRAN_LOWER_SUPPORT_UTILS_H
96