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