forked from OSchip/llvm-project
[flang] BaseObjects and static data placeholder
Original-commit: flang-compiler/f18@3ddfd5cadf Reviewed-on: https://github.com/flang-compiler/f18/pull/225 Tree-same-pre-rewrite: false
This commit is contained in:
parent
916ed9eab2
commit
3eb69047df
|
@ -22,6 +22,7 @@ add_library(FortranEvaluate
|
|||
intrinsics.cc
|
||||
logical.cc
|
||||
real.cc
|
||||
static-data.cc
|
||||
tools.cc
|
||||
type.cc
|
||||
variable.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 << '}';
|
||||
}
|
||||
}
|
|
@ -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 <cinttypes>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
class StaticDataObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<StaticDataObject>;
|
||||
|
||||
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<std::uint8_t> &data() const { return data_; }
|
||||
std::vector<std::uint8_t> &data() { return data_; }
|
||||
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
private:
|
||||
StaticDataObject() {}
|
||||
|
||||
std::string name_;
|
||||
int alignment_{0};
|
||||
std::vector<std::uint8_t> data_;
|
||||
};
|
||||
}
|
||||
#endif // FORTRAN_EVALUATE_STATIC_DATA_H_
|
|
@ -113,7 +113,12 @@ Expr<SubscriptInteger> 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<SubscriptInteger>{object->data().size()});
|
||||
}},
|
||||
parent_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,16 +136,12 @@ void Substring::Fold(FoldingContext &context) {
|
|||
first_ = AsExpr(Constant<SubscriptInteger>{1});
|
||||
}
|
||||
if (!last_.has_value()) {
|
||||
last_ = parent_.LEN();
|
||||
last_ = last();
|
||||
}
|
||||
*last_ = evaluate::Fold(context, std::move(**last_));
|
||||
if (std::optional<std::int64_t> ubi{ToInt64(**last_)}) {
|
||||
if (*ubi < 1) {
|
||||
*ubi = 0;
|
||||
last_ = AsExpr(Constant<SubscriptInteger>{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<SubscriptInteger>{1});
|
||||
last_ = AsExpr(Constant<SubscriptInteger>{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<typename A>
|
||||
|
@ -198,6 +199,12 @@ std::ostream &Emit(std::ostream &o, const CopyableIndirection<A> &p,
|
|||
return o;
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
std::ostream &Emit(std::ostream &o, const std::shared_ptr<A> &p) {
|
||||
CHECK(p != nullptr);
|
||||
return Emit(o, *p);
|
||||
}
|
||||
|
||||
template<typename... A>
|
||||
std::ostream &Emit(std::ostream &o, const std::variant<A...> &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<typename T> std::ostream &Designator<T>::Dump(std::ostream &o) const {
|
|||
static Expr<SubscriptInteger> SymbolLEN(const Symbol &sym) {
|
||||
return AsExpr(Constant<SubscriptInteger>{0}); // TODO
|
||||
}
|
||||
|
||||
Expr<SubscriptInteger> BaseObject::LEN() const {
|
||||
return std::visit(
|
||||
common::visitors{[](const Symbol *symbol) { return SymbolLEN(*symbol); },
|
||||
[](const StaticDataObject::Pointer &object) {
|
||||
return AsExpr(Constant<SubscriptInteger>{object->data().size()});
|
||||
}},
|
||||
u);
|
||||
}
|
||||
|
||||
Expr<SubscriptInteger> Component::LEN() const {
|
||||
return SymbolLEN(GetLastSymbol());
|
||||
}
|
||||
Expr<SubscriptInteger> 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<SubscriptInteger> CoarrayRef::LEN() const {
|
||||
|
@ -340,12 +359,20 @@ Expr<SubscriptInteger> 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<typename T> int Designator<T>::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<typename T> const Symbol &Designator<T>::GetFirstSymbol() const {
|
||||
return *std::visit(common::visitors{[](const Symbol *sym) { return sym; },
|
||||
[=](const auto &x) { return &x.GetFirstSymbol(); }},
|
||||
|
||||
template<typename T> BaseObject Designator<T>::GetBaseObject() const {
|
||||
return std::visit(
|
||||
common::visitors{[](const Symbol *symbol) { return BaseObject{*symbol}; },
|
||||
[](const auto &x) {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>,
|
||||
Substring>) {
|
||||
return x.GetBaseObject();
|
||||
} else {
|
||||
return BaseObject{x.GetFirstSymbol()};
|
||||
}
|
||||
}},
|
||||
u);
|
||||
}
|
||||
template<typename T> const Symbol &Designator<T>::GetLastSymbol() const {
|
||||
return *std::visit(common::visitors{[](const Symbol *sym) { return sym; },
|
||||
[=](const auto &x) { return &x.GetLastSymbol(); }},
|
||||
|
||||
template<typename T> const Symbol *Designator<T>::GetLastSymbol() const {
|
||||
return std::visit(
|
||||
common::visitors{[](const Symbol *symbol) { return symbol; },
|
||||
[](const auto &x) {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>,
|
||||
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<typename T> std::optional<DynamicType> Designator<T>::GetType() const {
|
||||
if constexpr (std::is_same_v<Result, SomeDerived>) {
|
||||
return GetSymbolType(GetLastSymbol());
|
||||
if (const Symbol * symbol{GetLastSymbol()}) {
|
||||
return GetSymbolType(*symbol);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
return {Result::GetType()};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<DynamicType> ProcedureDesignator::GetType() const {
|
||||
if (const Symbol * symbol{GetSymbol()}) {
|
||||
return {GetSymbolType(*symbol)};
|
||||
|
|
|
@ -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<typename A> 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<SubscriptInteger> LEN() const;
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
std::variant<const Symbol *, StaticDataObject::Pointer> 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<Subscript> &&ss)
|
||||
: u{&n}, subscript(std::move(ss)) {}
|
||||
ArrayRef(const Symbol &symbol, std::vector<Subscript> &&ss)
|
||||
: u{&symbol}, subscript(std::move(ss)) {}
|
||||
ArrayRef(Component &&c, std::vector<Subscript> &&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<Expr<SubscriptInteger>> &&first,
|
||||
std::optional<Expr<SubscriptInteger>> &&last)
|
||||
: parent_{std::move(parent)} {
|
||||
SetBounds(first, last);
|
||||
}
|
||||
|
||||
Expr<SubscriptInteger> first() const;
|
||||
Expr<SubscriptInteger> last() const;
|
||||
int Rank() const;
|
||||
const Symbol &GetFirstSymbol() const;
|
||||
const Symbol &GetLastSymbol() const;
|
||||
BaseObject GetBaseObject() const;
|
||||
const Symbol *GetLastSymbol() const;
|
||||
Expr<SubscriptInteger> LEN() const;
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
|
@ -199,7 +217,7 @@ public:
|
|||
private:
|
||||
void SetBounds(std::optional<Expr<SubscriptInteger>> &,
|
||||
std::optional<Expr<SubscriptInteger>> &);
|
||||
DataRef parent_;
|
||||
std::variant<DataRef, StaticDataObject::Pointer> parent_;
|
||||
std::optional<IndirectSubscriptIntegerExpr> first_, last_;
|
||||
};
|
||||
|
||||
|
@ -248,8 +266,8 @@ public:
|
|||
|
||||
std::optional<DynamicType> GetType() const;
|
||||
int Rank() const;
|
||||
const Symbol &GetFirstSymbol() const;
|
||||
const Symbol &GetLastSymbol() const;
|
||||
BaseObject GetBaseObject() const;
|
||||
const Symbol *GetLastSymbol() const;
|
||||
Expr<SubscriptInteger> LEN() const;
|
||||
std::ostream &Dump(std::ostream &o) const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue