FLANG
Utils.h
1//===-- Optimizer/Support/Utils.h -------------------------------*- 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_OPTIMIZER_SUPPORT_UTILS_H
14#define FORTRAN_OPTIMIZER_SUPPORT_UTILS_H
15
16#include "flang/Optimizer/Builder/FIRBuilder.h"
17#include "flang/Optimizer/Builder/Todo.h"
18#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
19#include "flang/Optimizer/Dialect/FIROps.h"
20#include "flang/Optimizer/Dialect/FIRType.h"
21#include "flang/Optimizer/Support/FatalError.h"
22#include "flang/Support/default-kinds.h"
23#include "mlir/Dialect/Arith/IR/Arith.h"
24#include "mlir/Dialect/Func/IR/FuncOps.h"
25#include "mlir/IR/BuiltinAttributes.h"
26#include "mlir/IR/BuiltinOps.h"
27#include "mlir/IR/Location.h"
28#include "mlir/Interfaces/FunctionInterfaces.h"
29#include "llvm/ADT/StringRef.h"
30#include <string>
31
32#include "flang/Optimizer/CodeGen/TypeConverter.h"
33
34namespace fir {
36inline uint32_t getLineFromLoc(mlir::Location loc) {
37 uint32_t line = 1;
38 if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(loc))
39 line = fileLoc.getLine();
40 return line;
41}
42
44inline std::int64_t toInt(mlir::arith::ConstantOp cop) {
45 return mlir::cast<mlir::IntegerAttr>(cop.getValue())
46 .getValue()
47 .getSExtValue();
48}
49
50// Translate front-end KINDs for use in the IR and code gen.
51inline std::vector<fir::KindTy>
52fromDefaultKinds(const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) {
53 return {static_cast<fir::KindTy>(defKinds.GetDefaultKind(
54 Fortran::common::TypeCategory::Character)),
55 static_cast<fir::KindTy>(
56 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Complex)),
57 static_cast<fir::KindTy>(defKinds.doublePrecisionKind()),
58 static_cast<fir::KindTy>(
59 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Integer)),
60 static_cast<fir::KindTy>(
61 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Logical)),
62 static_cast<fir::KindTy>(
63 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Real))};
64}
65
66inline std::string mlirTypeToString(mlir::Type type) {
67 std::string result{};
68 llvm::raw_string_ostream sstream(result);
69 sstream << type;
70 return result;
71}
72
73inline std::optional<int> mlirFloatTypeToKind(mlir::Type type) {
74 if (type.isF16())
75 return 2;
76 else if (type.isBF16())
77 return 3;
78 else if (type.isF32())
79 return 4;
80 else if (type.isF64())
81 return 8;
82 else if (type.isF80())
83 return 10;
84 else if (type.isF128())
85 return 16;
86 return std::nullopt;
87}
88
89inline std::string mlirTypeToIntrinsicFortran(fir::FirOpBuilder &builder,
90 mlir::Type type,
91 mlir::Location loc,
92 const llvm::Twine &name) {
93 if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(type)) {
94 if (std::optional<int> kind = mlirFloatTypeToKind(type))
95 return "REAL(KIND="s + std::to_string(*kind) + ")";
96 } else if (auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(type)) {
97 if (std::optional<int> kind = mlirFloatTypeToKind(cplxTy.getElementType()))
98 return "COMPLEX(KIND="s + std::to_string(*kind) + ")";
99 } else if (type.isUnsignedInteger()) {
100 if (type.isInteger(8))
101 return "UNSIGNED(KIND=1)";
102 else if (type.isInteger(16))
103 return "UNSIGNED(KIND=2)";
104 else if (type.isInteger(32))
105 return "UNSIGNED(KIND=4)";
106 else if (type.isInteger(64))
107 return "UNSIGNED(KIND=8)";
108 else if (type.isInteger(128))
109 return "UNSIGNED(KIND=16)";
110 } else if (type.isInteger(8))
111 return "INTEGER(KIND=1)";
112 else if (type.isInteger(16))
113 return "INTEGER(KIND=2)";
114 else if (type.isInteger(32))
115 return "INTEGER(KIND=4)";
116 else if (type.isInteger(64))
117 return "INTEGER(KIND=8)";
118 else if (type.isInteger(128))
119 return "INTEGER(KIND=16)";
120 else if (type == fir::LogicalType::get(builder.getContext(), 1))
121 return "LOGICAL(KIND=1)";
122 else if (type == fir::LogicalType::get(builder.getContext(), 2))
123 return "LOGICAL(KIND=2)";
124 else if (type == fir::LogicalType::get(builder.getContext(), 4))
125 return "LOGICAL(KIND=4)";
126 else if (type == fir::LogicalType::get(builder.getContext(), 8))
127 return "LOGICAL(KIND=8)";
128
129 fir::emitFatalError(loc, "unsupported type in " + name + ": " +
130 fir::mlirTypeToString(type));
131}
132
133inline void intrinsicTypeTODO(fir::FirOpBuilder &builder, mlir::Type type,
134 mlir::Location loc,
135 const llvm::Twine &intrinsicName) {
136 TODO(loc,
137 "intrinsic: " +
138 fir::mlirTypeToIntrinsicFortran(builder, type, loc, intrinsicName) +
139 " in " + intrinsicName);
140}
141
142inline void intrinsicTypeTODO2(fir::FirOpBuilder &builder, mlir::Type type1,
143 mlir::Type type2, mlir::Location loc,
144 const llvm::Twine &intrinsicName) {
145 TODO(loc,
146 "intrinsic: {" +
147 fir::mlirTypeToIntrinsicFortran(builder, type2, loc, intrinsicName) +
148 ", " +
149 fir::mlirTypeToIntrinsicFortran(builder, type2, loc, intrinsicName) +
150 "} in " + intrinsicName);
151}
152
153inline std::pair<Fortran::common::TypeCategory, KindMapping::KindTy>
154mlirTypeToCategoryKind(mlir::Location loc, mlir::Type type) {
155 if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(type)) {
156 if (std::optional<int> kind = mlirFloatTypeToKind(type))
157 return {Fortran::common::TypeCategory::Real, *kind};
158 } else if (auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(type)) {
159 if (std::optional<int> kind = mlirFloatTypeToKind(cplxTy.getElementType()))
160 return {Fortran::common::TypeCategory::Complex, *kind};
161 } else if (type.isInteger(8))
162 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
163 : Fortran::common::TypeCategory::Integer,
164 1};
165 else if (type.isInteger(16))
166 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
167 : Fortran::common::TypeCategory::Integer,
168 2};
169 else if (type.isInteger(32))
170 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
171 : Fortran::common::TypeCategory::Integer,
172 4};
173 else if (type.isInteger(64))
174 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
175 : Fortran::common::TypeCategory::Integer,
176 8};
177 else if (type.isInteger(128))
178 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
179 : Fortran::common::TypeCategory::Integer,
180 16};
181 else if (auto logicalType = mlir::dyn_cast<fir::LogicalType>(type))
182 return {Fortran::common::TypeCategory::Logical, logicalType.getFKind()};
183 else if (auto charType = mlir::dyn_cast<fir::CharacterType>(type))
184 return {Fortran::common::TypeCategory::Character, charType.getFKind()};
185 else if (mlir::isa<fir::RecordType>(type))
186 return {Fortran::common::TypeCategory::Derived, 0};
187 fir::emitFatalError(loc, "unsupported type: " + fir::mlirTypeToString(type));
188}
189
194fir::TypeInfoOp
195lookupTypeInfoOp(fir::RecordType recordType, mlir::ModuleOp module,
196 const mlir::SymbolTable *symbolTable = nullptr);
197
202fir::TypeInfoOp
203lookupTypeInfoOp(llvm::StringRef name, mlir::ModuleOp module,
204 const mlir::SymbolTable *symbolTable = nullptr);
205
209std::optional<llvm::ArrayRef<int64_t>> getComponentLowerBoundsIfNonDefault(
210 fir::RecordType recordType, llvm::StringRef component,
211 mlir::ModuleOp module, const mlir::SymbolTable *symbolTable = nullptr);
212
215std::optional<bool>
216isRecordWithFinalRoutine(fir::RecordType recordType, mlir::ModuleOp module,
217 const mlir::SymbolTable *symbolTable = nullptr);
218
220mlir::LLVM::ConstantOp
221genConstantIndex(mlir::Location loc, mlir::Type ity,
222 mlir::ConversionPatternRewriter &rewriter,
223 std::int64_t offset);
224
229mlir::Value computeElementDistance(mlir::Location loc,
230 mlir::Type llvmObjectType, mlir::Type idxTy,
231 mlir::ConversionPatternRewriter &rewriter,
232 const mlir::DataLayout &dataLayout);
233
234// Compute the alloc scale size (constant factors encoded in the array type).
235// We do this for arrays without a constant interior or arrays of character with
236// dynamic length arrays, since those are the only ones that get decayed to a
237// pointer to the element type.
238mlir::Value genAllocationScaleSize(mlir::Location loc, mlir::Type dataTy,
239 mlir::Type ity,
240 mlir::ConversionPatternRewriter &rewriter);
241
246mlir::Value integerCast(const fir::LLVMTypeConverter &converter,
247 mlir::Location loc,
248 mlir::ConversionPatternRewriter &rewriter,
249 mlir::Type ty, mlir::Value val, bool fold = false);
250
256std::optional<bool> isNewAllocationResult(mlir::OpResult result);
257
260std::string getPresentableFunctionName(mlir::FunctionOpInterface func);
261} // namespace fir
262
263#endif // FORTRAN_OPTIMIZER_SUPPORT_UTILS_H
Definition default-kinds.h:26
Definition AbstractConverter.h:37
uint32_t getLineFromLoc(mlir::Location loc)
Return the line of a location, or 1 if it does not carry one.
Definition Utils.h:36
mlir::Value integerCast(const fir::LLVMTypeConverter &converter, mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, mlir::Type ty, mlir::Value val, bool fold=false)
Definition Utils.cpp:110
std::string getPresentableFunctionName(mlir::FunctionOpInterface func)
Definition Utils.cpp:152
std::optional< bool > isNewAllocationResult(mlir::OpResult result)
Definition Utils.cpp:135
std::optional< bool > isRecordWithFinalRoutine(fir::RecordType recordType, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:55
std::optional< llvm::ArrayRef< int64_t > > getComponentLowerBoundsIfNonDefault(fir::RecordType recordType, llvm::StringRef component, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:40
std::int64_t toInt(mlir::arith::ConstantOp cop)
Return the integer value of a arith::ConstantOp.
Definition Utils.h:44
fir::TypeInfoOp lookupTypeInfoOp(fir::RecordType recordType, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:18
mlir::LLVM::ConstantOp genConstantIndex(mlir::Location loc, mlir::Type ity, mlir::ConversionPatternRewriter &rewriter, std::int64_t offset)
Generate a LLVM constant value of type ity, using the provided offset.
Definition Utils.cpp:65
void emitFatalError(mlir::Location loc, const llvm::Twine &message, bool genCrashDiag=true)
Definition FatalError.h:25
mlir::Value computeElementDistance(mlir::Location loc, mlir::Type llvmObjectType, mlir::Type idxTy, mlir::ConversionPatternRewriter &rewriter, const mlir::DataLayout &dataLayout)
Definition Utils.cpp:73