13#ifndef FORTRAN_LOWER_BOXANALYZER_H
14#define FORTRAN_LOWER_BOXANALYZER_H
16#include "flang/Evaluate/fold.h"
17#include "flang/Lower/Support/Utils.h"
18#include "flang/Optimizer/Dialect/FIRType.h"
19#include "flang/Optimizer/Support/Matcher.h"
32using FromBox = std::monostate;
41 static constexpr bool staticSize() {
return true; }
42 static constexpr bool isChar() {
return false; }
43 static constexpr bool isArray() {
return false; }
54 int64_t charLen()
const {
return len; }
56 static constexpr bool isChar() {
return true; }
65 llvm::SmallVectorImpl<int64_t> &&lens)
66 :
ScalarSym{sym}, lens{std::move(lens)} {}
80 std::optional<Fortran::lower::SomeExpr> charLen()
const {
81 if (
auto *l = std::get_if<Fortran::lower::SomeExpr>(&len))
86 static constexpr bool staticSize() {
return false; }
87 static constexpr bool isChar() {
return true; }
90 std::variant<FromBox, Fortran::lower::SomeExpr> len;
96 llvm::SmallVectorImpl<Fortran::lower::SomeExpr> &&lens)
97 :
ScalarSym{sym}, lens{std::move(lens)} {}
105 llvm::SmallVectorImpl<int64_t> &&shapes)
106 : lbounds{std::move(lbounds)}, shapes{std::move(shapes)} {}
108 static constexpr bool staticSize() {
return true; }
109 static constexpr bool isArray() {
return true; }
110 bool lboundAllOnes()
const {
111 return llvm::all_of(lbounds, [](int64_t v) {
return v == 1; });
121 llvm::SmallVectorImpl<int64_t> &&lbounds,
122 llvm::SmallVectorImpl<int64_t> &&shapes)
126 static constexpr bool staticSize() {
return LBoundsAndShape::staticSize(); }
131 llvm::SmallVectorImpl<const Fortran::semantics::ShapeSpec *> &&bounds)
132 : bounds{std::move(bounds)} {}
134 static constexpr bool staticSize() {
return false; }
135 static constexpr bool isArray() {
return true; }
136 bool lboundAllOnes()
const {
138 if (
auto low = p->lbound().GetExplicit())
139 if (
auto lb = Fortran::evaluate::ToInt64(*low))
152 llvm::SmallVectorImpl<const Fortran::semantics::ShapeSpec *> &&bounds)
155 static constexpr bool staticSize() {
return DynamicBound::staticSize(); }
161 llvm::SmallVectorImpl<int64_t> &&lbounds,
162 llvm::SmallVectorImpl<int64_t> &&shapes)
164 std::move(shapes)} {}
166 static constexpr bool staticSize() {
167 return ScalarStaticChar::staticSize() && LBoundsAndShape::staticSize();
175 llvm::SmallVectorImpl<int64_t> &&lbounds,
176 llvm::SmallVectorImpl<int64_t> &&shapes)
178 std::move(shapes)} {}
180 llvm::SmallVectorImpl<int64_t> &&lbounds,
181 llvm::SmallVectorImpl<int64_t> &&shapes)
183 std::move(shapes)} {}
185 static constexpr bool staticSize() {
186 return ScalarDynamicChar::staticSize() && LBoundsAndShape::staticSize();
194 llvm::SmallVectorImpl<const Fortran::semantics::ShapeSpec *> &&bounds)
197 static constexpr bool staticSize() {
198 return ScalarStaticChar::staticSize() && DynamicBound::staticSize();
207 llvm::SmallVectorImpl<const Fortran::semantics::ShapeSpec *> &&bounds)
211 llvm::SmallVectorImpl<const Fortran::semantics::ShapeSpec *> &&bounds)
214 static constexpr bool staticSize() {
215 return ScalarDynamicChar::staticSize() && DynamicBound::staticSize();
224 return sym.GetType()->category() ==
225 Fortran::semantics::DeclTypeSpec::Character;
231 return det && det->IsArray();
237 return det && det->IsArray() && det->shape().IsExplicitShape();
241 return Fortran::semantics::IsAssumedSizeArray(sym.GetUltimate());
254 using None = std::monostate;
278 operator bool()
const {
return !std::holds_alternative<None>(box); }
280 bool isTrivial()
const {
return std::holds_alternative<ScalarSym>(box); }
290 [](
const auto &) {
return false; });
295 return match([](
const StaticArray &) {
return true; },
301 [](
const auto &) {
return false; });
307 return match([](
const StaticArray &) {
return true; },
310 [](
const auto &) {
return false; });
313 bool isConstant()
const {
315 [](
const None &) ->
bool {
316 llvm::report_fatal_error(
"internal: analysis failed");
318 [](
const auto &x) {
return x.staticSize(); });
321 std::optional<int64_t> getCharLenConst()
const {
322 using A = std::optional<int64_t>;
324 [](
const ScalarStaticChar &x) -> A {
return {x.charLen()}; },
325 [](
const StaticArrayStaticChar &x) -> A {
return {x.charLen()}; },
326 [](
const DynamicArrayStaticChar &x) -> A {
return {x.charLen()}; },
327 [](
const auto &) -> A {
return std::nullopt; });
330 std::optional<Fortran::lower::SomeExpr> getCharLenExpr()
const {
331 using A = std::optional<Fortran::lower::SomeExpr>;
332 return match([](
const ScalarDynamicChar &x) {
return x.charLen(); },
333 [](
const StaticArrayDynamicChar &x) {
return x.charLen(); },
334 [](
const DynamicArrayDynamicChar &x) {
return x.charLen(); },
335 [](
const auto &) -> A {
return std::nullopt; });
341 [&](
const StaticArray &x) {
return x.lboundAllOnes(); },
342 [&](
const DynamicArray &x) {
return x.lboundAllOnes(); },
347 [](
const auto &) ->
bool { llvm::report_fatal_error(
"not an array"); });
353 return match([](
const StaticArray &x) -> A {
return x.lbounds; },
356 [](
const auto &) -> A {
357 llvm::report_fatal_error(
"does not have static lbounds");
364 return match([](
const StaticArray &x) -> A {
return x.shapes; },
367 [](
const auto &) -> A {
368 llvm::report_fatal_error(
"does not have static shape");
375 return match([](
const DynamicArray &x) -> A {
return x.bounds; },
378 [](
const auto &) -> A {
379 llvm::report_fatal_error(
"does not have bounds");
385 if (Fortran::semantics::IsProcedurePointer(sym))
387 if (symIsArray(sym)) {
388 bool isConstant = !isAssumedSize(sym);
393 bounds.push_back(&subs);
396 if (
auto low = subs.lbound().GetExplicit()) {
397 if (
auto lb = Fortran::evaluate::ToInt64(*low)) {
398 lbounds.push_back(*lb);
399 if (
auto high = subs.ubound().GetExplicit()) {
400 if (
auto ub = Fortran::evaluate::ToInt64(*high)) {
401 int64_t extent = *ub - *lb + 1;
402 shapes.push_back(extent < 0 ? 0 : extent);
405 }
else if (subs.ubound().isStar()) {
406 assert(Fortran::semantics::IsNamedConstant(sym) &&
407 "expect implied shape constant");
408 shapes.push_back(fir::SequenceType::getUnknownExtent());
417 if (symIsChar(sym)) {
418 if (
auto len = charLenConstant(sym)) {
426 if (
auto var = charLenVariable(sym)) {
444 box =
StaticArray(sym, std::move(lbounds), std::move(shapes));
451 if (symIsChar(sym)) {
452 if (
auto len = charLenConstant(sym))
454 else if (
auto var = charLenVariable(sym))
465 const VT &matchee()
const {
return box; }
471 return sym.GetUltimate()
477 std::optional<int64_t>
479 if (std::optional<Fortran::lower::SomeExpr> expr = charLenVariable(sym))
480 if (std::optional<int64_t> asInt = Fortran::evaluate::ToInt64(*expr)) {
490 std::optional<Fortran::lower::SomeExpr>
493 sym.GetType()->characterTypeSpec().length();
494 if (Fortran::semantics::MaybeIntExpr expr = lenParam.GetExplicit())
495 return {Fortran::evaluate::AsGenericExpr(std::move(*expr))};
498 if (sym.attrs().test(Fortran::semantics::Attr::PARAMETER))
499 if (
const auto *objectDetails =
502 if (objectDetails->init())
503 if (
const auto *charExpr = std::get_if<
505 &objectDetails->init()->u))
506 if (Fortran::semantics::MaybeSubscriptIntExpr expr =
508 return {Fortran::evaluate::AsGenericExpr(std::move(*expr))};
Definition: BoxAnalyzer.h:251
bool isChar() const
Returns true for any sort of CHARACTER.
Definition: BoxAnalyzer.h:283
llvm::ArrayRef< int64_t > staticLBound() const
Get the static lbound values (the origin of the array).
Definition: BoxAnalyzer.h:351
bool lboundIsAllOnes() const
Is the origin of this array the default of vector of 1?
Definition: BoxAnalyzer.h:339
bool isStaticArray() const
Definition: BoxAnalyzer.h:306
bool isArray() const
Returns true for any sort of array.
Definition: BoxAnalyzer.h:294
void analyze(const Fortran::semantics::Symbol &sym)
Run the analysis on sym.
Definition: BoxAnalyzer.h:384
llvm::ArrayRef< const Fortran::semantics::ShapeSpec * > dynamicBound() const
Get the dynamic bounds information of the array (both origin, shape).
Definition: BoxAnalyzer.h:373
llvm::ArrayRef< int64_t > staticShape() const
Get the static extents of the array.
Definition: BoxAnalyzer.h:362
Definition: AbstractConverter.h:59
Array of CHARACTER with dynamic LEN, origin, and shape.
Definition: BoxAnalyzer.h:203
Array of CHARACTER with constant LEN but dynamic origin, shape.
Definition: BoxAnalyzer.h:191
Array of T with dynamic origin and/or shape.
Definition: BoxAnalyzer.h:149
Definition: BoxAnalyzer.h:129
Definition: BoxAnalyzer.h:103
Scalar of dependent type CHARACTER, dynamic LEN.
Definition: BoxAnalyzer.h:73
Scalar of dependent type Derived, dynamic LEN(s).
Definition: BoxAnalyzer.h:94
Scalar of dependent type CHARACTER, constant LEN.
Definition: BoxAnalyzer.h:50
Scalar of dependent type Derived, constant LEN(s).
Definition: BoxAnalyzer.h:63
Base class for all box analysis results.
Definition: BoxAnalyzer.h:35
Array of CHARACTER with dynamic LEN but constant origin, shape.
Definition: BoxAnalyzer.h:172
Array of CHARACTER with statically known LEN, origin, and shape.
Definition: BoxAnalyzer.h:159
Array of T with statically known origin (lbounds) and shape.
Definition: BoxAnalyzer.h:119