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