Mercurial > hg > CbC > CbC_llvm
view flang/lib/Evaluate/constant.cpp @ 248:cfe92afade2b
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 16 Aug 2023 18:23:14 +0900 |
parents | c4bab56944e8 |
children | 1f2b6ac9f198 |
line wrap: on
line source
//===-- lib/Evaluate/constant.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "flang/Evaluate/constant.h" #include "flang/Evaluate/expression.h" #include "flang/Evaluate/shape.h" #include "flang/Evaluate/type.h" #include <string> namespace Fortran::evaluate { ConstantBounds::ConstantBounds(const ConstantSubscripts &shape) : shape_(shape), lbounds_(shape_.size(), 1) {} ConstantBounds::ConstantBounds(ConstantSubscripts &&shape) : shape_(std::move(shape)), lbounds_(shape_.size(), 1) {} ConstantBounds::~ConstantBounds() = default; void ConstantBounds::set_lbounds(ConstantSubscripts &&lb) { CHECK(lb.size() == shape_.size()); lbounds_ = std::move(lb); for (std::size_t j{0}; j < shape_.size(); ++j) { if (shape_[j] == 0) { lbounds_[j] = 1; } } } ConstantSubscripts ConstantBounds::ComputeUbounds( std::optional<int> dim) const { if (dim) { CHECK(*dim < Rank()); return {lbounds_[*dim] + shape_[*dim] - 1}; } else { ConstantSubscripts ubounds(Rank()); for (int i{0}; i < Rank(); ++i) { ubounds[i] = lbounds_[i] + shape_[i] - 1; } return ubounds; } } void ConstantBounds::SetLowerBoundsToOne() { for (auto &n : lbounds_) { n = 1; } } Constant<SubscriptInteger> ConstantBounds::SHAPE() const { return AsConstantShape(shape_); } ConstantSubscript ConstantBounds::SubscriptsToOffset( const ConstantSubscripts &index) const { CHECK(GetRank(index) == GetRank(shape_)); ConstantSubscript stride{1}, offset{0}; int dim{0}; for (auto j : index) { auto lb{lbounds_[dim]}; auto extent{shape_[dim++]}; CHECK(j >= lb && j < lb + extent); offset += stride * (j - lb); stride *= extent; } return offset; } std::size_t TotalElementCount(const ConstantSubscripts &shape) { return static_cast<std::size_t>(GetSize(shape)); } bool ConstantBounds::IncrementSubscripts( ConstantSubscripts &indices, const std::vector<int> *dimOrder) const { int rank{GetRank(shape_)}; CHECK(GetRank(indices) == rank); CHECK(!dimOrder || static_cast<int>(dimOrder->size()) == rank); for (int j{0}; j < rank; ++j) { ConstantSubscript k{dimOrder ? (*dimOrder)[j] : j}; auto lb{lbounds_[k]}; CHECK(indices[k] >= lb); if (++indices[k] < lb + shape_[k]) { return true; } else { CHECK(indices[k] == lb + std::max<ConstantSubscript>(shape_[k], 1)); indices[k] = lb; } } return false; // all done } std::optional<std::vector<int>> ValidateDimensionOrder( int rank, const std::vector<int> &order) { std::vector<int> dimOrder(rank); if (static_cast<int>(order.size()) == rank) { std::bitset<common::maxRank> seenDimensions; for (int j{0}; j < rank; ++j) { int dim{order[j]}; if (dim < 1 || dim > rank || seenDimensions.test(dim - 1)) { return std::nullopt; } dimOrder[j] = dim - 1; seenDimensions.set(dim - 1); } return dimOrder; } else { return std::nullopt; } } bool HasNegativeExtent(const ConstantSubscripts &shape) { for (ConstantSubscript extent : shape) { if (extent < 0) { return true; } } return false; } template <typename RESULT, typename ELEMENT> ConstantBase<RESULT, ELEMENT>::ConstantBase( std::vector<Element> &&x, ConstantSubscripts &&sh, Result res) : ConstantBounds(std::move(sh)), result_{res}, values_(std::move(x)) { CHECK(size() == TotalElementCount(shape())); } template <typename RESULT, typename ELEMENT> ConstantBase<RESULT, ELEMENT>::~ConstantBase() {} template <typename RESULT, typename ELEMENT> bool ConstantBase<RESULT, ELEMENT>::operator==(const ConstantBase &that) const { return shape() == that.shape() && values_ == that.values_; } template <typename RESULT, typename ELEMENT> auto ConstantBase<RESULT, ELEMENT>::Reshape( const ConstantSubscripts &dims) const -> std::vector<Element> { std::size_t n{TotalElementCount(dims)}; CHECK(!empty() || n == 0); std::vector<Element> elements; auto iter{values().cbegin()}; while (n-- > 0) { elements.push_back(*iter); if (++iter == values().cend()) { iter = values().cbegin(); } } return elements; } template <typename RESULT, typename ELEMENT> std::size_t ConstantBase<RESULT, ELEMENT>::CopyFrom( const ConstantBase<RESULT, ELEMENT> &source, std::size_t count, ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { std::size_t copied{0}; ConstantSubscripts sourceSubscripts{source.lbounds()}; while (copied < count) { values_.at(SubscriptsToOffset(resultSubscripts)) = source.values_.at(source.SubscriptsToOffset(sourceSubscripts)); copied++; source.IncrementSubscripts(sourceSubscripts); IncrementSubscripts(resultSubscripts, dimOrder); } return copied; } template <typename T> auto Constant<T>::At(const ConstantSubscripts &index) const -> Element { return Base::values_.at(Base::SubscriptsToOffset(index)); } template <typename T> auto Constant<T>::Reshape(ConstantSubscripts &&dims) const -> Constant { return {Base::Reshape(dims), std::move(dims)}; } template <typename T> std::size_t Constant<T>::CopyFrom(const Constant<T> &source, std::size_t count, ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { return Base::CopyFrom(source, count, resultSubscripts, dimOrder); } // Constant<Type<TypeCategory::Character, KIND> specializations template <int KIND> Constant<Type<TypeCategory::Character, KIND>>::Constant( const Scalar<Result> &str) : values_{str}, length_{static_cast<ConstantSubscript>(values_.size())} {} template <int KIND> Constant<Type<TypeCategory::Character, KIND>>::Constant(Scalar<Result> &&str) : values_{std::move(str)}, length_{static_cast<ConstantSubscript>( values_.size())} {} template <int KIND> Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len, std::vector<Scalar<Result>> &&strings, ConstantSubscripts &&sh) : ConstantBounds(std::move(sh)), length_{len} { CHECK(strings.size() == TotalElementCount(shape())); values_.assign(strings.size() * length_, static_cast<typename Scalar<Result>::value_type>(' ')); ConstantSubscript at{0}; for (const auto &str : strings) { auto strLen{static_cast<ConstantSubscript>(str.size())}; if (strLen > length_) { values_.replace(at, length_, str.substr(0, length_)); } else { values_.replace(at, strLen, str); } at += length_; } CHECK(at == static_cast<ConstantSubscript>(values_.size())); } template <int KIND> Constant<Type<TypeCategory::Character, KIND>>::~Constant() {} template <int KIND> bool Constant<Type<TypeCategory::Character, KIND>>::empty() const { return size() == 0; } template <int KIND> std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const { if (length_ == 0) { return TotalElementCount(shape()); } else { return static_cast<ConstantSubscript>(values_.size()) / length_; } } template <int KIND> auto Constant<Type<TypeCategory::Character, KIND>>::At( const ConstantSubscripts &index) const -> Scalar<Result> { auto offset{SubscriptsToOffset(index)}; return values_.substr(offset * length_, length_); } template <int KIND> auto Constant<Type<TypeCategory::Character, KIND>>::Substring( ConstantSubscript lo, ConstantSubscript hi) const -> std::optional<Constant> { std::vector<Element> elements; ConstantSubscript n{GetSize(shape())}; ConstantSubscript newLength{0}; if (lo > hi) { // zero-length results while (n-- > 0) { elements.emplace_back(); // "" } } else if (lo < 1 || hi > length_) { return std::nullopt; } else { newLength = hi - lo + 1; for (ConstantSubscripts at{lbounds()}; n-- > 0; IncrementSubscripts(at)) { elements.emplace_back(At(at).substr(lo - 1, newLength)); } } return Constant{newLength, std::move(elements), ConstantSubscripts{shape()}}; } template <int KIND> auto Constant<Type<TypeCategory::Character, KIND>>::Reshape( ConstantSubscripts &&dims) const -> Constant<Result> { std::size_t n{TotalElementCount(dims)}; CHECK(!empty() || n == 0); std::vector<Element> elements; ConstantSubscript at{0}, limit{static_cast<ConstantSubscript>(values_.size())}; while (n-- > 0) { elements.push_back(values_.substr(at, length_)); at += length_; if (at == limit) { // subtle: at > limit somehow? substr() will catch it at = 0; } } return {length_, std::move(elements), std::move(dims)}; } template <int KIND> std::size_t Constant<Type<TypeCategory::Character, KIND>>::CopyFrom( const Constant<Type<TypeCategory::Character, KIND>> &source, std::size_t count, ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { CHECK(length_ == source.length_); if (length_ == 0) { // It's possible that the array of strings consists of all empty strings. // If so, constant folding will result in a string that's completely empty // and the length_ will be zero, and there's nothing to do. return count; } else { std::size_t copied{0}; std::size_t elementBytes{length_ * sizeof(decltype(values_[0]))}; ConstantSubscripts sourceSubscripts{source.lbounds()}; while (copied < count) { auto *dest{&values_.at(SubscriptsToOffset(resultSubscripts) * length_)}; const auto *src{&source.values_.at( source.SubscriptsToOffset(sourceSubscripts) * length_)}; std::memcpy(dest, src, elementBytes); copied++; source.IncrementSubscripts(sourceSubscripts); IncrementSubscripts(resultSubscripts, dimOrder); } return copied; } } // Constant<SomeDerived> specialization Constant<SomeDerived>::Constant(const StructureConstructor &x) : Base{x.values(), Result{x.derivedTypeSpec()}} {} Constant<SomeDerived>::Constant(StructureConstructor &&x) : Base{std::move(x.values()), Result{x.derivedTypeSpec()}} {} Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec, std::vector<StructureConstructorValues> &&x, ConstantSubscripts &&s) : Base{std::move(x), std::move(s), Result{spec}} {} static std::vector<StructureConstructorValues> AcquireValues( std::vector<StructureConstructor> &&x) { std::vector<StructureConstructorValues> result; for (auto &&structure : std::move(x)) { result.emplace_back(std::move(structure.values())); } return result; } Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec, std::vector<StructureConstructor> &&x, ConstantSubscripts &&shape) : Base{AcquireValues(std::move(x)), std::move(shape), Result{spec}} {} std::optional<StructureConstructor> Constant<SomeDerived>::GetScalarValue() const { if (Rank() == 0) { return StructureConstructor{result().derivedTypeSpec(), values_.at(0)}; } else { return std::nullopt; } } StructureConstructor Constant<SomeDerived>::At( const ConstantSubscripts &index) const { return {result().derivedTypeSpec(), values_.at(SubscriptsToOffset(index))}; } auto Constant<SomeDerived>::Reshape(ConstantSubscripts &&dims) const -> Constant { return {result().derivedTypeSpec(), Base::Reshape(dims), std::move(dims)}; } std::size_t Constant<SomeDerived>::CopyFrom(const Constant<SomeDerived> &source, std::size_t count, ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { return Base::CopyFrom(source, count, resultSubscripts, dimOrder); } bool ComponentCompare::operator()(SymbolRef x, SymbolRef y) const { return semantics::SymbolSourcePositionCompare{}(x, y); } #ifdef _MSC_VER // disable bogus warning about missing definitions #pragma warning(disable : 4661) #endif INSTANTIATE_CONSTANT_TEMPLATES } // namespace Fortran::evaluate