• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 namespace Fortran::evaluate {
22 
23 class InitialImage {
24 public:
25   enum Result {
26     Ok,
27     NotAConstant,
28     OutOfRange,
29     SizeMismatch,
30   };
31 
InitialImage(std::size_t bytes)32   explicit InitialImage(std::size_t bytes) : data_(bytes) {}
33 
size()34   std::size_t size() const { return data_.size(); }
35 
Add(ConstantSubscript,std::size_t,const A &)36   template <typename A> Result Add(ConstantSubscript, std::size_t, const A &) {
37     return NotAConstant;
38   }
39   template <typename T>
Add(ConstantSubscript offset,std::size_t bytes,const Constant<T> & x)40   Result Add(
41       ConstantSubscript offset, std::size_t bytes, const Constant<T> &x) {
42     if (offset < 0 || offset + bytes > data_.size()) {
43       return OutOfRange;
44     } else {
45       auto elementBytes{ToInt64(x.GetType().MeasureSizeInBytes())};
46       if (!elementBytes ||
47           bytes !=
48               x.values().size() * static_cast<std::size_t>(*elementBytes)) {
49         return SizeMismatch;
50       } else {
51         std::memcpy(&data_.at(offset), &x.values().at(0), bytes);
52         return Ok;
53       }
54     }
55   }
56   template <int KIND>
Add(ConstantSubscript offset,std::size_t bytes,const Constant<Type<TypeCategory::Character,KIND>> & x)57   Result Add(ConstantSubscript offset, std::size_t bytes,
58       const Constant<Type<TypeCategory::Character, KIND>> &x) {
59     if (offset < 0 || offset + bytes > data_.size()) {
60       return OutOfRange;
61     } else {
62       auto elements{TotalElementCount(x.shape())};
63       auto elementBytes{bytes > 0 ? bytes / elements : 0};
64       if (elements * elementBytes != bytes) {
65         return SizeMismatch;
66       } else {
67         for (auto at{x.lbounds()}; elements-- > 0; x.IncrementSubscripts(at)) {
68           auto scalar{x.At(at)}; // this is a std string; size() in chars
69           // Subtle: an initializer for a substring may have been
70           // expanded to the length of the entire string.
71           auto scalarBytes{scalar.size() * KIND};
72           if (scalarBytes < elementBytes ||
73               (scalarBytes > elementBytes && elements != 0)) {
74             return SizeMismatch;
75           }
76           std::memcpy(&data_[offset], scalar.data(), elementBytes);
77           offset += elementBytes;
78         }
79         return Ok;
80       }
81     }
82   }
83   Result Add(ConstantSubscript, std::size_t, const Constant<SomeDerived> &);
84   template <typename T>
Add(ConstantSubscript offset,std::size_t bytes,const Expr<T> & x)85   Result Add(ConstantSubscript offset, std::size_t bytes, const Expr<T> &x) {
86     return std::visit(
87         [&](const auto &y) { return Add(offset, bytes, y); }, x.u);
88   }
89 
90   void AddPointer(ConstantSubscript, const Expr<SomeType> &);
91 
92   void Incorporate(ConstantSubscript, const InitialImage &);
93 
94   // Conversions to constant initializers
95   std::optional<Expr<SomeType>> AsConstant(FoldingContext &,
96       const DynamicType &, const ConstantSubscripts &,
97       ConstantSubscript offset = 0) const;
98   std::optional<Expr<SomeType>> AsConstantDataPointer(
99       const DynamicType &, ConstantSubscript offset = 0) const;
100   const ProcedureDesignator &AsConstantProcPointer(
101       ConstantSubscript offset = 0) const;
102 
103   friend class AsConstantHelper;
104   friend class AsConstantDataPointerHelper;
105 
106 private:
107   std::vector<char> data_;
108   std::map<ConstantSubscript, Expr<SomeType>> pointers_;
109 };
110 
111 } // namespace Fortran::evaluate
112 #endif // FORTRAN_EVALUATE_INITIAL_IMAGE_H_
113