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