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