Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Evaluate/fold-designator.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#ifndef FORTRAN_EVALUATE_FOLD_DESIGNATOR_H_
10#define FORTRAN_EVALUATE_FOLD_DESIGNATOR_H_
11
12// Resolves a designator at compilation time to a base symbol, a byte offset
13// from that symbol, and a byte size. Also resolves in the reverse direction,
14// reconstructing a designator from a symbol, byte offset, and size.
15// Used for resolving variables in DATA statements to ranges in their
16// initial images.
17// Some designators can also be folded into constant pointer descriptors,
18// which also have per-dimension extent and stride information suitable
19// for initializing a descriptor.
20// (The designators that cannot be folded are those with vector-valued
21// subscripts; they are allowed as DATA statement objects, but are not valid
22// initial pointer targets.)
23
24#include "common.h"
25#include "expression.h"
26#include "fold.h"
27#include "shape.h"
28#include "type.h"
29#include "variable.h"
30#include <optional>
31#include <variant>
32
33namespace Fortran::evaluate {
34
35using common::ConstantSubscript;
36
37// Identifies a single contiguous interval of bytes at a fixed offset
38// from a known symbol.
39class OffsetSymbol {
40public:
41 OffsetSymbol(const Symbol &symbol, std::size_t bytes)
42 : symbol_{symbol}, size_{bytes} {}
43 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(OffsetSymbol)
44
45 const Symbol &symbol() const { return *symbol_; }
46 void set_symbol(const Symbol &symbol) { symbol_ = symbol; };
47 ConstantSubscript offset() const { return offset_; }
48 void Augment(ConstantSubscript n) { offset_ += n; }
49 std::size_t size() const { return size_; }
50 void set_size(std::size_t bytes) { size_ = bytes; }
51
52private:
53 SymbolRef symbol_;
54 ConstantSubscript offset_{0};
55 std::size_t size_;
56};
57
58// Folds a Designator<T> into a sequence of OffsetSymbols, if it can
59// be so folded. Array sections yield multiple results, each
60// corresponding to an element in array element order.
61class DesignatorFolder {
62public:
63 explicit DesignatorFolder(FoldingContext &c, bool getLastComponent = false)
64 : context_{c}, getLastComponent_{getLastComponent} {}
65
66 bool isEmpty() const { return isEmpty_; }
67 bool isOutOfRange() const { return isOutOfRange_; }
68
69 template <typename T>
70 std::optional<OffsetSymbol> FoldDesignator(const Expr<T> &expr) {
71 return common::visit(
72 [&](const auto &x) { return FoldDesignator(x, elementNumber_++); },
73 expr.u);
74 }
75
76private:
77 std::optional<OffsetSymbol> FoldDesignator(const Symbol &, ConstantSubscript);
78 std::optional<OffsetSymbol> FoldDesignator(
79 const SymbolRef &x, ConstantSubscript which) {
80 return FoldDesignator(*x, which);
81 }
82 std::optional<OffsetSymbol> FoldDesignator(
83 const ArrayRef &, ConstantSubscript);
84 std::optional<OffsetSymbol> FoldDesignator(
85 const Component &, ConstantSubscript);
86 std::optional<OffsetSymbol> FoldDesignator(
87 const ComplexPart &, ConstantSubscript);
88 std::optional<OffsetSymbol> FoldDesignator(
89 const Substring &, ConstantSubscript);
90 std::optional<OffsetSymbol> FoldDesignator(
91 const DataRef &, ConstantSubscript);
92 std::optional<OffsetSymbol> FoldDesignator(
93 const NamedEntity &, ConstantSubscript);
94 std::optional<OffsetSymbol> FoldDesignator(
95 const CoarrayRef &, ConstantSubscript);
96 std::optional<OffsetSymbol> FoldDesignator(
97 const ProcedureDesignator &, ConstantSubscript);
98
99 template <typename T>
100 std::optional<OffsetSymbol> FoldDesignator(
101 const Expr<T> &expr, ConstantSubscript which) {
102 return common::visit(
103 [&](const auto &x) { return FoldDesignator(x, which); }, expr.u);
104 }
105
106 template <typename A>
107 std::optional<OffsetSymbol> FoldDesignator(const A &, ConstantSubscript) {
108 return std::nullopt;
109 }
110
111 template <typename T>
112 std::optional<OffsetSymbol> FoldDesignator(
113 const Designator<T> &designator, ConstantSubscript which) {
114 return common::visit(
115 [&](const auto &x) { return FoldDesignator(x, which); }, designator.u);
116 }
117 template <int KIND>
118 std::optional<OffsetSymbol> FoldDesignator(
119 const Designator<Type<TypeCategory::Character, KIND>> &designator,
120 ConstantSubscript which) {
121 return common::visit(
122 common::visitors{
123 [&](const Substring &ss) {
124 if (const auto *dataRef{ss.GetParentIf<DataRef>()}) {
125 if (auto result{FoldDesignator(*dataRef, which)}) {
126 if (auto start{ToInt64(ss.lower())}) {
127 std::optional<ConstantSubscript> end;
128 auto len{dataRef->LEN()};
129 if (ss.upper()) {
130 end = ToInt64(*ss.upper());
131 } else if (len) {
132 end = ToInt64(*len);
133 }
134 if (end) {
135 if (*start < 1) {
136 isOutOfRange_ = true;
137 }
138 result->Augment(KIND * (*start - 1));
139 result->set_size(
140 *end >= *start ? KIND * (*end - *start + 1) : 0);
141 if (len) {
142 if (auto lenVal{ToInt64(*len)}) {
143 if (*end > *lenVal) {
144 isOutOfRange_ = true;
145 }
146 }
147 }
148 return result;
149 }
150 }
151 }
152 }
153 return std::optional<OffsetSymbol>{};
154 },
155 [&](const auto &x) { return FoldDesignator(x, which); },
156 },
157 designator.u);
158 }
159
160 FoldingContext &context_;
161 bool getLastComponent_{false};
162 ConstantSubscript elementNumber_{0}; // zero-based
163 bool isEmpty_{false};
164 bool isOutOfRange_{false};
165};
166
167// Reconstructs a Designator<> from a symbol and an offset.
168std::optional<Expr<SomeType>> OffsetToDesignator(
169 FoldingContext &, const Symbol &, ConstantSubscript offset, std::size_t);
170std::optional<Expr<SomeType>> OffsetToDesignator(
171 FoldingContext &, const OffsetSymbol &);
172
173// Represents a compile-time constant Descriptor suitable for use
174// as a pointer initializer. Lower bounds are always 1.
175struct ConstantObjectPointer : public OffsetSymbol {
176 struct Dimension {
177 ConstantSubscript byteStride;
178 ConstantSubscript extent;
179 };
180 using Dimensions = std::vector<Dimension>;
181
182 ConstantObjectPointer(
183 const Symbol &symbol, std::size_t size, Dimensions &&dims)
184 : OffsetSymbol{symbol, size}, dimensions{std::move(dims)} {}
185
186 // Folds a designator to a constant pointer. Crashes on failure.
187 // Use IsInitialDataTarget() to validate the expression beforehand.
188 static ConstantObjectPointer From(FoldingContext &, const Expr<SomeType> &);
189
190 Dimensions dimensions;
191};
192
193} // namespace Fortran::evaluate
194#endif // FORTRAN_EVALUATE_FOLD_DESIGNATOR_H_
195

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Evaluate/fold-designator.h