//===-- ComponentPath.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_LOWER_COMPONENTPATH_H
#define FORTRAN_LOWER_COMPONENTPATH_H
#include "flang/Lower/IterationSpace.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
namespace fir {
class ArrayLoadOp;
}
namespace Fortran::evaluate {
class ArrayRef;
}
namespace Fortran::lower {
namespace details {
class ImplicitSubscripts {};
} // namespace details
using PathComponent =
std::variant<const evaluate::ArrayRef *, const evaluate::Component *,
const evaluate::ComplexPart *, details::ImplicitSubscripts>;
/// Collection of components.
///
/// This class is used both to collect front-end post-order functional Expr
/// trees and their translations to Values to be used in a pre-order list of
/// arguments.
class ComponentPath {
public:
using ExtendRefFunc = std::function<mlir::Value(const mlir::Value &)>;
ComponentPath(bool isImplicit) { setPC(isImplicit); }
ComponentPath(bool isImplicit, const evaluate::Substring *ss)
: substring(ss) {
setPC(isImplicit);
}
ComponentPath() = delete;
bool isSlice() const { return !trips.empty() || hasComponents(); }
bool hasComponents() const { return !suffixComponents.empty(); }
void clear();
bool hasExtendCoorRef() const { return extendCoorRef.has_value(); }
ExtendRefFunc getExtendCoorRef() const;
void resetExtendCoorRef() { extendCoorRef = std::nullopt; }
void resetPC();
llvm::SmallVector<PathComponent> reversePath;
const evaluate::Substring *substring = nullptr;
bool applied = false;
llvm::SmallVector<mlir::Value> prefixComponents;
llvm::SmallVector<mlir::Value> trips;
llvm::SmallVector<mlir::Value> suffixComponents;
std::function<IterationSpace(const IterationSpace &)> pc;
/// In the case where a path of components involves members that are POINTER
/// or ALLOCATABLE, a dereference is required in FIR for semantic correctness.
/// This optional continuation allows the generation of those dereferences.
/// These accesses are always on Fortran entities of record types, which are
/// implicitly in-memory objects.
std::optional<ExtendRefFunc> extendCoorRef;
private:
void setPC(bool isImplicit);
};
/// Examine each subscript expression of \p x and return true if and only if any
/// of the subscripts is a vector or has a rank greater than 0.
bool isRankedArrayAccess(const Fortran::evaluate::ArrayRef &x);
} // namespace Fortran::lower
#endif // FORTRAN_LOWER_COMPONENTPATH_H