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 <map>
18#include <optional>
19#include <vector>
20
21namespace Fortran::evaluate {
22
23class InitialImage {
24public:
25 enum Result {
26 Ok,
27 OkNoChange,
28 NotAConstant,
29 OutOfRange,
30 SizeMismatch,
31 LengthMismatch,
32 TooManyElems,
33 };
34
35 explicit InitialImage(std::size_t bytes) : data_(bytes) {}
36 InitialImage(InitialImage &&that) = default;
37
38 std::size_t size() const { return data_.size(); }
39
40 template <typename A>
41 Result Add(ConstantSubscript, std::size_t, const A &, FoldingContext &) {
42 return NotAConstant;
43 }
44 template <typename T>
45 Result Add(ConstantSubscript offset, std::size_t bytes, const Constant<T> &x,
46 FoldingContext &context) {
47 if (offset < 0 || offset + bytes > data_.size()) {
48 return OutOfRange;
49 } else {
50 auto elementBytes{ToInt64(x.GetType().MeasureSizeInBytes(context, true))};
51 if (!elementBytes ||
52 bytes !=
53 x.values().size() * static_cast<std::size_t>(*elementBytes)) {
54 return SizeMismatch;
55 } else if (bytes == 0) {
56 return OkNoChange;
57 } else {
58 // TODO endianness
59 auto *to{&data_.at(offset)};
60 const auto *from{&x.values().at(0)};
61 if (std::memcmp(to, from, bytes) == 0) {
62 return OkNoChange;
63 } else {
64 std::memcpy(to, from, bytes);
65 return Ok;
66 }
67 }
68 }
69 }
70 template <int KIND>
71 Result Add(ConstantSubscript offset, std::size_t bytes,
74 if (offset < 0 || offset + bytes > data_.size()) {
75 return OutOfRange;
76 } else {
77 auto optElements{TotalElementCount(x.shape())};
78 if (!optElements) {
79 return TooManyElems;
80 }
81 auto elements{*optElements};
82 auto elementBytes{bytes > 0 ? bytes / elements : 0};
83 if (elements * elementBytes != bytes) {
84 return SizeMismatch;
85 } else if (bytes == 0) {
86 return OkNoChange;
87 } else {
88 Result result{OkNoChange};
89 for (auto at{x.lbounds()}; elements-- > 0; x.IncrementSubscripts(at)) {
90 auto scalar{x.At(at)}; // this is a std string; size() in chars
91 auto scalarBytes{scalar.size() * KIND};
92 if (scalarBytes != elementBytes) {
93 result = LengthMismatch;
94 }
95 // Blank padding when short
96 for (; scalarBytes < elementBytes; scalarBytes += KIND) {
97 scalar += ' ';
98 }
99 // TODO endianness
100 auto *to{&data_.at(offset)};
101 const auto *from{scalar.data()};
102 if (std::memcmp(to, from, elementBytes) != 0) {
103 std::memcpy(to, from, elementBytes);
104 if (result == OkNoChange) {
105 result = Ok;
106 }
107 }
108 offset += elementBytes;
109 }
110 return result;
111 }
112 }
113 }
114 Result Add(ConstantSubscript, std::size_t, const Constant<SomeDerived> &,
116 template <typename T>
117 Result Add(ConstantSubscript offset, std::size_t bytes, const Expr<T> &x,
118 FoldingContext &c) {
119 return common::visit(
120 [&](const auto &y) { return Add(offset, bytes, y, c); }, x.u);
121 }
122
123 Result AddPointer(ConstantSubscript, const Expr<SomeType> &);
124
125 // Returns true if anything changes
126 bool Incorporate(ConstantSubscript toOffset, const InitialImage &from,
127 ConstantSubscript fromOffset, ConstantSubscript bytes);
128
129 // Conversions to constant initializers
130 std::optional<Expr<SomeType>> AsConstant(FoldingContext &,
131 const DynamicType &, std::optional<std::int64_t> charLength,
132 const ConstantSubscripts &, bool padWithZero = false,
133 ConstantSubscript offset = 0) const;
134 std::optional<Expr<SomeType>> AsConstantPointer(
135 ConstantSubscript offset = 0) const;
136
137 friend class AsConstantHelper;
138
139private:
140 std::vector<char> data_;
141 std::map<ConstantSubscript, Expr<SomeType>> pointers_;
142};
143
144} // namespace Fortran::evaluate
145#endif // FORTRAN_EVALUATE_INITIAL_IMAGE_H_
Definition constant.h:147
Definition type.h:74
Definition common.h:214
Definition common.h:216
Definition type.h:57
Definition call.h:34