From 3eb69047dfa28930850ce9d04f54c231d1b28f3d Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 2 Nov 2018 14:13:12 -0700 Subject: [PATCH] [flang] BaseObjects and static data placeholder Original-commit: flang-compiler/f18@3ddfd5cadfafffe9c58cedd7a625cd071820c79c Reviewed-on: https://github.com/flang-compiler/f18/pull/225 Tree-same-pre-rewrite: false --- flang/lib/evaluate/CMakeLists.txt | 1 + flang/lib/evaluate/static-data.cc | 30 ++++++++ flang/lib/evaluate/static-data.h | 66 +++++++++++++++++ flang/lib/evaluate/variable.cc | 148 +++++++++++++++++++++++++++++--------- flang/lib/evaluate/variable.h | 32 +++++++-- 5 files changed, 237 insertions(+), 40 deletions(-) create mode 100644 flang/lib/evaluate/static-data.cc create mode 100644 flang/lib/evaluate/static-data.h diff --git a/flang/lib/evaluate/CMakeLists.txt b/flang/lib/evaluate/CMakeLists.txt index 8fed50a..e54fafc 100644 --- a/flang/lib/evaluate/CMakeLists.txt +++ b/flang/lib/evaluate/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(FortranEvaluate intrinsics.cc logical.cc real.cc + static-data.cc tools.cc type.cc variable.cc diff --git a/flang/lib/evaluate/static-data.cc b/flang/lib/evaluate/static-data.cc new file mode 100644 index 0000000..f9748f4 --- /dev/null +++ b/flang/lib/evaluate/static-data.cc @@ -0,0 +1,30 @@ +// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "static-data.h" + +namespace Fortran::evaluate { +std::ostream &StaticDataObject::Dump(std::ostream &o) const { + o << "static data "; + char sep{'{'}; + for (std::uint8_t byte : data_) { + o << sep << "0x" << std::hex << byte; + sep = ','; + } + if (sep == '{') { + o << '{'; + } + return o << '}'; +} +} diff --git a/flang/lib/evaluate/static-data.h b/flang/lib/evaluate/static-data.h new file mode 100644 index 0000000..d6a073ee --- /dev/null +++ b/flang/lib/evaluate/static-data.h @@ -0,0 +1,66 @@ +// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FORTRAN_EVALUATE_STATIC_DATA_H_ +#define FORTRAN_EVALUATE_STATIC_DATA_H_ + +// Represents constant static data objects + +#include "type.h" +#include "../common/idioms.h" +#include +#include +#include +#include + +namespace Fortran::evaluate { + +class StaticDataObject { +public: + using Pointer = std::shared_ptr; + + StaticDataObject(const StaticDataObject &) = delete; + StaticDataObject(StaticDataObject &&) = delete; + StaticDataObject &operator=(const StaticDataObject &) = delete; + StaticDataObject &operator=(StaticDataObject &&) = delete; + + static Pointer Create() { return Pointer{new StaticDataObject}; } + + const std::string &name() const { return name_; } + StaticDataObject &set_name(std::string n) { + name_ = n; + return *this; + } + + int alignment() const { return alignment_; } + StaticDataObject &set_alignment(int a) { + CHECK(a >= 0); + alignment_ = a; + return *this; + } + + const std::vector &data() const { return data_; } + std::vector &data() { return data_; } + + std::ostream &Dump(std::ostream &) const; + +private: + StaticDataObject() {} + + std::string name_; + int alignment_{0}; + std::vector data_; +}; +} +#endif // FORTRAN_EVALUATE_STATIC_DATA_H_ diff --git a/flang/lib/evaluate/variable.cc b/flang/lib/evaluate/variable.cc index d3db661..844e410 100644 --- a/flang/lib/evaluate/variable.cc +++ b/flang/lib/evaluate/variable.cc @@ -113,7 +113,12 @@ Expr Substring::last() const { if (last_.has_value()) { return **last_; } else { - return parent_.LEN(); + return std::visit( + common::visitors{[](const DataRef &dataRef) { return dataRef.LEN(); }, + [](const StaticDataObject::Pointer &object) { + return AsExpr(Constant{object->data().size()}); + }}, + parent_); } } @@ -131,16 +136,12 @@ void Substring::Fold(FoldingContext &context) { first_ = AsExpr(Constant{1}); } if (!last_.has_value()) { - last_ = parent_.LEN(); + last_ = last(); } *last_ = evaluate::Fold(context, std::move(**last_)); if (std::optional ubi{ToInt64(**last_)}) { - if (*ubi < 1) { - *ubi = 0; - last_ = AsExpr(Constant{0}); - } - if (lbi.has_value() && *ubi < *lbi) { - // This case is well defined + if (*ubi < 1 || (lbi.has_value() && *ubi < *lbi)) { + // Zero-length string: canonicalize first_ = AsExpr(Constant{1}); last_ = AsExpr(Constant{0}); } @@ -158,11 +159,11 @@ template<> std::ostream &Emit(std::ostream &o, const std::string &lit) { } template<> std::ostream &Emit(std::ostream &o, const std::u16string &lit) { - return o << "TODO: dumping CHARACTER*2"; + return o << parser::QuoteCharacterLiteral(lit); } template<> std::ostream &Emit(std::ostream &o, const std::u32string &lit) { - return o << "TODO: dumping CHARACTER*4"; + return o << parser::QuoteCharacterLiteral(lit); } template @@ -198,6 +199,12 @@ std::ostream &Emit(std::ostream &o, const CopyableIndirection &p, return o; } +template +std::ostream &Emit(std::ostream &o, const std::shared_ptr &p) { + CHECK(p != nullptr); + return Emit(o, *p); +} + template std::ostream &Emit(std::ostream &o, const std::variant &u) { std::visit([&](const auto &x) { Emit(o, x); }, u); @@ -212,6 +219,8 @@ template<> std::ostream &Emit(std::ostream &o, const IntrinsicProcedure &p) { return o << p; } +std::ostream &BaseObject::Dump(std::ostream &o) const { return Emit(o, u); } + std::ostream &Component::Dump(std::ostream &o) const { base_->Dump(o); return Emit(o << '%', symbol_); @@ -293,13 +302,23 @@ template std::ostream &Designator::Dump(std::ostream &o) const { static Expr SymbolLEN(const Symbol &sym) { return AsExpr(Constant{0}); // TODO } + +Expr BaseObject::LEN() const { + return std::visit( + common::visitors{[](const Symbol *symbol) { return SymbolLEN(*symbol); }, + [](const StaticDataObject::Pointer &object) { + return AsExpr(Constant{object->data().size()}); + }}, + u); +} + Expr Component::LEN() const { return SymbolLEN(GetLastSymbol()); } Expr ArrayRef::LEN() const { return std::visit( - common::visitors{[](const Symbol *s) { return SymbolLEN(*s); }, - [](const Component &x) { return x.LEN(); }}, + common::visitors{[](const Symbol *symbol) { return SymbolLEN(*symbol); }, + [](const Component &component) { return component.LEN(); }}, u); } Expr CoarrayRef::LEN() const { @@ -340,12 +359,20 @@ Expr ProcedureDesignator::LEN() const { } // Rank() +int BaseObject::Rank() const { + return std::visit( + common::visitors{[](const Symbol *symbol) { return symbol->Rank(); }, + [](const StaticDataObject::Pointer &) { return 0; }}, + u); +} + int Component::Rank() const { int baseRank{base_->Rank()}; int symbolRank{symbol_->Rank()}; CHECK(baseRank == 0 || symbolRank == 0); return baseRank + symbolRank; } + int Subscript::Rank() const { return std::visit(common::visitors{[](const IndirectSubscriptIntegerExpr &x) { int rank{x->Rank()}; @@ -355,6 +382,7 @@ int Subscript::Rank() const { [](const Triplet &) { return 1; }}, u); } + int ArrayRef::Rank() const { int rank{0}; for (std::size_t j{0}; j < subscript.size(); ++j) { @@ -368,6 +396,7 @@ int ArrayRef::Rank() const { return baseRank + rank; } } + int CoarrayRef::Rank() const { int rank{0}; for (std::size_t j{0}; j < subscript_.size(); ++j) { @@ -375,6 +404,7 @@ int CoarrayRef::Rank() const { } return rank; } + int DataRef::Rank() const { return std::visit( // g++ 7.2 emits bogus warnings here and below when common::visitors{} @@ -390,7 +420,14 @@ int DataRef::Rank() const { }, u); } -int Substring::Rank() const { return parent_.Rank(); } + +int Substring::Rank() const { + return std::visit( + common::visitors{[](const DataRef &dataRef) { return dataRef.Rank(); }, + [](const StaticDataObject::Pointer &) { return 0; }}, + parent_); +} + int ComplexPart::Rank() const { return complex_.Rank(); } template int Designator::Rank() const { return std::visit( @@ -420,17 +457,20 @@ bool ProcedureDesignator::IsElemental() const { return 0; } -// GetFirstSymbol() & GetLastSymbol() +// GetBaseObject(), GetFirstSymbol(), & GetLastSymbol() const Symbol &Component::GetFirstSymbol() const { return base_->GetFirstSymbol(); } + const Symbol &ArrayRef::GetFirstSymbol() const { - return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, - [=](const Component &component) { - return &component.GetFirstSymbol(); - }}, + return *std::visit( + common::visitors{[](const Symbol *symbol) { return symbol; }, + [=](const Component &component) { + return &component.GetFirstSymbol(); + }}, u); } + const Symbol &ArrayRef::GetLastSymbol() const { return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, [=](const Component &component) { @@ -438,32 +478,69 @@ const Symbol &ArrayRef::GetLastSymbol() const { }}, u); } + const Symbol &DataRef::GetFirstSymbol() const { - return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, - [=](const auto &x) { return &x.GetFirstSymbol(); }}, + return *std::visit( + common::visitors{[](const Symbol *symbol) { return symbol; }, + [](const auto &x) { return &x.GetFirstSymbol(); }}, u); } + const Symbol &DataRef::GetLastSymbol() const { - return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, - [=](const auto &x) { return &x.GetLastSymbol(); }}, + return *std::visit( + common::visitors{[](const Symbol *symbol) { return symbol; }, + [](const auto &x) { return &x.GetLastSymbol(); }}, u); } -const Symbol &Substring::GetFirstSymbol() const { - return parent_.GetFirstSymbol(); + +BaseObject Substring::GetBaseObject() const { + return std::visit(common::visitors{[](const DataRef &dataRef) { + return BaseObject{ + dataRef.GetFirstSymbol()}; + }, + + [](StaticDataObject::Pointer pointer) { + return BaseObject{std::move(pointer)}; + }}, + parent_); } -const Symbol &Substring::GetLastSymbol() const { - return parent_.GetLastSymbol(); + +const Symbol *Substring::GetLastSymbol() const { + return std::visit(common::visitors{[](const DataRef &dataRef) { + return &dataRef.GetLastSymbol(); + }, + [](const auto &) -> const Symbol * { return nullptr; }}, + parent_); } -template const Symbol &Designator::GetFirstSymbol() const { - return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, - [=](const auto &x) { return &x.GetFirstSymbol(); }}, + +template BaseObject Designator::GetBaseObject() const { + return std::visit( + common::visitors{[](const Symbol *symbol) { return BaseObject{*symbol}; }, + [](const auto &x) { + if constexpr (std::is_same_v, + Substring>) { + return x.GetBaseObject(); + } else { + return BaseObject{x.GetFirstSymbol()}; + } + }}, u); } -template const Symbol &Designator::GetLastSymbol() const { - return *std::visit(common::visitors{[](const Symbol *sym) { return sym; }, - [=](const auto &x) { return &x.GetLastSymbol(); }}, + +template const Symbol *Designator::GetLastSymbol() const { + return std::visit( + common::visitors{[](const Symbol *symbol) { return symbol; }, + [](const auto &x) { + if constexpr (std::is_same_v, + Substring>) { + return x.GetLastSymbol(); + } else { + return &x.GetLastSymbol(); + } + }}, u); } + const Symbol *ProcedureDesignator::GetSymbol() const { return std::visit(common::visitors{[](const Symbol *sym) { return sym; }, [](const Component &c) { return &c.GetLastSymbol(); }, @@ -473,11 +550,16 @@ const Symbol *ProcedureDesignator::GetSymbol() const { template std::optional Designator::GetType() const { if constexpr (std::is_same_v) { - return GetSymbolType(GetLastSymbol()); + if (const Symbol * symbol{GetLastSymbol()}) { + return GetSymbolType(*symbol); + } else { + return std::nullopt; + } } else { return {Result::GetType()}; } } + std::optional ProcedureDesignator::GetType() const { if (const Symbol * symbol{GetSymbol()}) { return {GetSymbolType(*symbol)}; diff --git a/flang/lib/evaluate/variable.h b/flang/lib/evaluate/variable.h index 7184be0..d0c18d9 100644 --- a/flang/lib/evaluate/variable.h +++ b/flang/lib/evaluate/variable.h @@ -23,6 +23,7 @@ #include "call.h" #include "common.h" +#include "static-data.h" #include "type.h" #include "../common/idioms.h" #include "../common/template.h" @@ -47,6 +48,17 @@ template struct Variable; int GetSymbolRank(const Symbol &); const parser::CharBlock &GetSymbolName(const Symbol &); +// Reference a base object in memory. This can be a Fortran symbol, +// static data (e.g., CHARACTER literal), or compiler-created temporary. +struct BaseObject { + CLASS_BOILERPLATE(BaseObject) + explicit BaseObject(const Symbol &symbol) : u{&symbol} {} + explicit BaseObject(StaticDataObject::Pointer &&p) : u{std::move(p)} {} + int Rank() const; + Expr LEN() const; + std::ostream &Dump(std::ostream &) const; + std::variant u; +}; // R913 structure-component & C920: Defined to be a multi-part // data-ref whose last part has no subscripts (or image-selector, although @@ -108,8 +120,8 @@ struct Subscript { // these types. struct ArrayRef { CLASS_BOILERPLATE(ArrayRef) - ArrayRef(const Symbol &n, std::vector &&ss) - : u{&n}, subscript(std::move(ss)) {} + ArrayRef(const Symbol &symbol, std::vector &&ss) + : u{&symbol}, subscript(std::move(ss)) {} ArrayRef(Component &&c, std::vector &&ss) : u{std::move(c)}, subscript(std::move(ss)) {} @@ -185,12 +197,18 @@ public: : parent_{std::move(parent)} { SetBounds(first, last); } + Substring(StaticDataObject::Pointer &&parent, + std::optional> &&first, + std::optional> &&last) + : parent_{std::move(parent)} { + SetBounds(first, last); + } Expr first() const; Expr last() const; int Rank() const; - const Symbol &GetFirstSymbol() const; - const Symbol &GetLastSymbol() const; + BaseObject GetBaseObject() const; + const Symbol *GetLastSymbol() const; Expr LEN() const; std::ostream &Dump(std::ostream &) const; @@ -199,7 +217,7 @@ public: private: void SetBounds(std::optional> &, std::optional> &); - DataRef parent_; + std::variant parent_; std::optional first_, last_; }; @@ -248,8 +266,8 @@ public: std::optional GetType() const; int Rank() const; - const Symbol &GetFirstSymbol() const; - const Symbol &GetLastSymbol() const; + BaseObject GetBaseObject() const; + const Symbol *GetLastSymbol() const; Expr LEN() const; std::ostream &Dump(std::ostream &o) const; -- 2.7.4