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