FLANG
initial-image.h
1//===-------include/flang/Evaluate/initial-image.h ------------------------===//
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_INITIAL_IMAGE_H_
10#define FORTRAN_EVALUATE_INITIAL_IMAGE_H_
11
12// Represents the initialized storage of an object during DATA statement
13// processing, including the conversion of that image to a constant
14// initializer for a symbol.
15
16#include "expression.h"
17#include "flang/Evaluate/char.h"
18#include <map>
19#include <optional>
20#include <vector>
21
22namespace Fortran::evaluate {
23
24template <typename SCALAR>
25inline void StoreSerialValues(char *dst, llvm::ArrayRef<SCALAR> values,
26 size_t elementSize, bool *changed = nullptr) {
27 for (auto [i, v] : llvm::enumerate(values)) {
28 v.StoreRawBytes(dst + i * elementSize, elementSize, changed);
29 }
30}
31
32template <typename SCALAR>
33inline void LoadSerialValues(
34 const char *src, llvm::MutableArrayRef<SCALAR> values, size_t stride) {
35 for (auto it : llvm::enumerate(values)) {
36 it.value() =
37 SCALAR::FromRawBytes(src + stride * it.index(), SCALAR::bytesStored());
38 }
39}
40
41class InitialImage {
42public:
43 enum Result {
44 Ok,
45 OkNoChange,
46 NotAConstant,
47 OutOfRange,
48 SizeMismatch,
49 LengthMismatch,
50 TooManyElems,
51 };
52
53 explicit InitialImage(std::size_t bytes) : data_(bytes) {}
54 InitialImage(InitialImage &&that) = default;
55
56 std::size_t size() const { return data_.size(); }
57
58 template <typename A>
59 Result Add(ConstantSubscript, std::size_t, const A &, FoldingContext &) {
60 return NotAConstant;
61 }
62 template <typename T>
63 Result Add(ConstantSubscript offset, std::size_t bytes, const Constant<T> &x,
64 FoldingContext &context) {
65 if (offset < 0 || offset + bytes > data_.size()) {
66 return OutOfRange;
67 } else {
68 auto elementBytes{ToInt64(x.GetType().MeasureSizeInBytes(context, true))};
69 if (!elementBytes ||
70 bytes !=
71 x.values().size() * static_cast<std::size_t>(*elementBytes)) {
72 return SizeMismatch;
73 } else if (bytes == 0) {
74 return OkNoChange;
75 } else {
76 // TODO endianness
77 bool changed{false};
78 StoreSerialValues<Scalar<T>>(&data_.at(offset),
79 llvm::ArrayRef<Scalar<T>>(x.values()), *elementBytes, &changed);
80 return changed ? Ok : OkNoChange;
81 }
82 }
83 }
84 template <int KIND>
85 Result Add(ConstantSubscript offset, std::size_t bytes,
88 if (offset < 0 || offset + bytes > data_.size()) {
89 return OutOfRange;
90 } else {
91 auto optElements{TotalElementCount(x.shape())};
92 if (!optElements) {
93 return TooManyElems;
94 }
95 auto elements{*optElements};
96 auto elementBytes{bytes > 0 ? bytes / elements : 0};
97 if (elements * elementBytes != bytes) {
98 return SizeMismatch;
99 } else if (bytes == 0) {
100 return OkNoChange;
101 } else {
102 Result result{OkNoChange};
103 for (auto at{x.lbounds()}; elements-- > 0; x.IncrementSubscripts(at)) {
104 typename value::Character<KIND> scalar{x.At(at)};
105 auto scalarBytes{scalar.size() * KIND};
106 if (scalarBytes != elementBytes) {
107 result = LengthMismatch;
108 }
109 // TODO endianness
110 auto *to{&data_.at(offset)};
111 bool changed{false};
112 scalar.StoreRawBytes(to, elementBytes, &changed);
113 if (changed && result == OkNoChange) {
114 result = Ok;
115 }
116 offset += elementBytes;
117 }
118 return result;
119 }
120 }
121 }
122 Result Add(ConstantSubscript, std::size_t, const Constant<SomeDerived> &,
124 template <typename T>
125 Result Add(ConstantSubscript offset, std::size_t bytes, const Expr<T> &x,
126 FoldingContext &c) {
127 return common::visit(
128 [&](const auto &y) { return Add(offset, bytes, y, c); }, x.u);
129 }
130
131 Result AddPointer(ConstantSubscript, const Expr<SomeType> &);
132
133 // Returns true if anything changes
134 bool Incorporate(ConstantSubscript toOffset, const InitialImage &from,
135 ConstantSubscript fromOffset, ConstantSubscript bytes);
136
137 // Conversions to constant initializers
138 std::optional<Expr<SomeType>> AsConstant(FoldingContext &,
139 const DynamicType &, std::optional<std::int64_t> charLength,
140 const ConstantSubscripts &, bool padWithZero = false,
141 ConstantSubscript offset = 0) const;
142 std::optional<Expr<SomeType>> AsConstantPointer(
143 ConstantSubscript offset = 0) const;
144
145 friend class AsConstantHelper;
146
147private:
148 std::vector<char> data_;
149 std::map<ConstantSubscript, Expr<SomeType>> pointers_;
150};
151
152} // namespace Fortran::evaluate
153#endif // FORTRAN_EVALUATE_INITIAL_IMAGE_H_
Definition constant.h:147
Definition type.h:73
Definition common.h:215
Definition common.h:217
Definition type.h:56
Simple wrapper around a std::string/std:u16string/stdu32string.
Definition char.h:18
Definition FIRType.h:106
Definition call.h:34