Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Evaluate/call.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ class ProcedureRef {

std::optional<Expr<SubscriptInteger>> LEN() const;
int Rank() const;
static constexpr int Corank() { return 0; } // TODO
bool IsElemental() const { return proc_.IsElemental(); }
bool hasAlternateReturns() const { return hasAlternateReturns_; }

Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Evaluate/characteristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class TypeAndShape {
}
if (auto type{x.GetType()}) {
TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
result.corank_ = GetCorank(x);
if (result.corank_ > 0) {
result.attrs_.set(Attr::Coarray);
}
if (type->category() == TypeCategory::Character) {
if (const auto *chExpr{UnwrapExpr<Expr<SomeCharacter>>(x)}) {
if (auto length{chExpr->LEN()}) {
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Evaluate/constant.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ConstantBounds {
~ConstantBounds();
const ConstantSubscripts &shape() const { return shape_; }
int Rank() const { return GetRank(shape_); }
static constexpr int Corank() { return 0; }
Constant<SubscriptInteger> SHAPE() const;

// It is possible in this representation for a constant array to have
Expand Down
11 changes: 9 additions & 2 deletions flang/include/flang/Evaluate/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ template <typename RESULT> class ExpressionBase {

std::optional<DynamicType> GetType() const;
int Rank() const;
int Corank() const;
std::string AsFortran() const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const;
Expand Down Expand Up @@ -190,6 +191,7 @@ class Operation {
return rank;
}
}
static constexpr int Corank() { return 0; }

bool operator==(const Operation &that) const {
return operand_ == that.operand_;
Expand Down Expand Up @@ -395,6 +397,7 @@ struct ImpliedDoIndex {
using Result = SubscriptInteger;
bool operator==(const ImpliedDoIndex &) const;
static constexpr int Rank() { return 0; }
static constexpr int Corank() { return 0; }
parser::CharBlock name; // nested implied DOs must use distinct names
};

Expand Down Expand Up @@ -441,6 +444,7 @@ template <typename RESULT> class ArrayConstructorValues {

bool operator==(const ArrayConstructorValues &) const;
static constexpr int Rank() { return 1; }
static constexpr int Corank() { return 0; }
template <typename A> common::NoLvalue<A> Push(A &&x) {
values_.emplace_back(std::move(x));
}
Expand Down Expand Up @@ -680,6 +684,7 @@ template <> class Relational<SomeType> {
int Rank() const {
return common::visit([](const auto &x) { return x.Rank(); }, u);
}
static constexpr int Corank() { return 0; }
llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
common::MapTemplate<Relational, DirectlyComparableTypes> u;
};
Expand Down Expand Up @@ -766,7 +771,8 @@ class StructureConstructor {
std::optional<Expr<SomeType>> Find(const Symbol &) const;

StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
int Rank() const { return 0; }
static constexpr int Rank() { return 0; }
static constexpr int Corank() { return 0; }
DynamicType GetType() const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;

Expand Down Expand Up @@ -820,7 +826,8 @@ using BOZLiteralConstant = typename LargestReal::Scalar::Word;
// Null pointers without MOLD= arguments are typed by context.
struct NullPointer {
constexpr bool operator==(const NullPointer &) const { return true; }
constexpr int Rank() const { return 0; }
static constexpr int Rank() { return 0; }
static constexpr int Corank() { return 0; }
};

// Procedure pointer targets are treated as if they were typeless.
Expand Down
30 changes: 17 additions & 13 deletions flang/include/flang/Evaluate/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,26 @@ template <typename A> bool IsAssumedRank(const A *x) {
return x && IsAssumedRank(*x);
}

// Predicate: true when an expression is a coarray (corank > 0)
bool IsCoarray(const ActualArgument &);
bool IsCoarray(const Symbol &);
template <typename A> bool IsCoarray(const A &) { return false; }
template <typename A> bool IsCoarray(const Designator<A> &designator) {
if (const auto *symbol{std::get_if<SymbolRef>(&designator.u)}) {
return IsCoarray(**symbol);
}
return false;
// Finds the corank of an entity, possibly packaged in various ways.
// Unlike rank, only data references have corank > 0.
int GetCorank(const ActualArgument &);
static inline int GetCorank(const Symbol &symbol) { return symbol.Corank(); }
template <typename A> int GetCorank(const A &) { return 0; }
template <typename T> int GetCorank(const Designator<T> &designator) {
return designator.Corank();
}
template <typename T> bool IsCoarray(const Expr<T> &expr) {
return common::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
template <typename T> int GetCorank(const Expr<T> &expr) {
return common::visit([](const auto &x) { return GetCorank(x); }, expr.u);
}
template <typename A> bool IsCoarray(const std::optional<A> &x) {
return x && IsCoarray(*x);
template <typename A> int GetCorank(const std::optional<A> &x) {
return x ? GetCorank(*x) : 0;
}
template <typename A> int GetCorank(const A *x) {
return x ? GetCorank(*x) : 0;
}

// Predicate: true when an expression is a coarray (corank > 0)
template <typename A> bool IsCoarray(const A &x) { return GetCorank(x) > 0; }

// Generalizing packagers: these take operations and expressions of more
// specific types and wrap them in Expr<> containers of more abstract types.
Expand Down
11 changes: 11 additions & 0 deletions flang/include/flang/Evaluate/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ template <typename T> struct Variable;
struct BaseObject {
EVALUATE_UNION_CLASS_BOILERPLATE(BaseObject)
int Rank() const;
int Corank() const;
std::optional<Expr<SubscriptInteger>> LEN() const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
const Symbol *symbol() const {
Expand Down Expand Up @@ -84,6 +85,7 @@ class Component {
SymbolRef &symbol() { return symbol_; }

int Rank() const;
int Corank() const;
const Symbol &GetFirstSymbol() const;
const Symbol &GetLastSymbol() const { return symbol_; }
std::optional<Expr<SubscriptInteger>> LEN() const;
Expand Down Expand Up @@ -116,6 +118,7 @@ class NamedEntity {
Component *UnwrapComponent();

int Rank() const;
int Corank() const;
std::optional<Expr<SubscriptInteger>> LEN() const;
bool operator==(const NamedEntity &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
Expand Down Expand Up @@ -147,6 +150,7 @@ class TypeParamInquiry {
const Symbol &parameter() const { return parameter_; }

static constexpr int Rank() { return 0; } // always scalar
static constexpr int Corank() { return 0; }
bool operator==(const TypeParamInquiry &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;

Expand Down Expand Up @@ -224,6 +228,7 @@ class ArrayRef {
}

int Rank() const;
int Corank() const;
const Symbol &GetFirstSymbol() const;
const Symbol &GetLastSymbol() const;
std::optional<Expr<SubscriptInteger>> LEN() const;
Expand Down Expand Up @@ -271,6 +276,7 @@ class CoarrayRef {
CoarrayRef &set_team(Expr<SomeInteger> &&, bool isTeamNumber = false);

int Rank() const;
int Corank() const { return 0; }
const Symbol &GetFirstSymbol() const;
const Symbol &GetLastSymbol() const;
NamedEntity GetBase() const;
Expand All @@ -294,6 +300,7 @@ class CoarrayRef {
struct DataRef {
EVALUATE_UNION_CLASS_BOILERPLATE(DataRef)
int Rank() const;
int Corank() const;
const Symbol &GetFirstSymbol() const;
const Symbol &GetLastSymbol() const;
std::optional<Expr<SubscriptInteger>> LEN() const;
Expand Down Expand Up @@ -331,6 +338,7 @@ class Substring {
Parent &parent() { return parent_; }

int Rank() const;
int Corank() const;
template <typename A> const A *GetParentIf() const {
return std::get_if<A>(&parent_);
}
Expand Down Expand Up @@ -361,6 +369,7 @@ class ComplexPart {
const DataRef &complex() const { return complex_; }
Part part() const { return part_; }
int Rank() const;
int Corank() const;
const Symbol &GetFirstSymbol() const { return complex_.GetFirstSymbol(); }
const Symbol &GetLastSymbol() const { return complex_.GetLastSymbol(); }
bool operator==(const ComplexPart &) const;
Expand Down Expand Up @@ -396,6 +405,7 @@ template <typename T> class Designator {

std::optional<DynamicType> GetType() const;
int Rank() const;
int Corank() const;
BaseObject GetBaseObject() const;
const Symbol *GetLastSymbol() const;
std::optional<Expr<SubscriptInteger>> LEN() const;
Expand All @@ -421,6 +431,7 @@ class DescriptorInquiry {
int dimension() const { return dimension_; }

static constexpr int Rank() { return 0; } // always scalar
static constexpr int Corank() { return 0; }
bool operator==(const DescriptorInquiry &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;

Expand Down
44 changes: 27 additions & 17 deletions flang/include/flang/Semantics/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -861,23 +861,7 @@ class Symbol {
bool operator!=(const Symbol &that) const { return !(*this == that); }

int Rank() const { return RankImpl(); }

int Corank() const {
return common::visit(
common::visitors{
[](const SubprogramDetails &sd) {
return sd.isFunction() ? sd.result().Corank() : 0;
},
[](const GenericDetails &) {
return 0; /*TODO*/
},
[](const UseDetails &x) { return x.symbol().Corank(); },
[](const HostAssocDetails &x) { return x.symbol().Corank(); },
[](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
[](const auto &) { return 0; },
},
details_);
}
int Corank() const { return CorankImpl(); }

// If there is a parent component, return a pointer to its derived type spec.
// The Scope * argument defaults to this->scope_ but should be overridden
Expand Down Expand Up @@ -955,6 +939,32 @@ class Symbol {
},
details_);
}
inline int CorankImpl(int depth = startRecursionDepth) const {
if (depth-- == 0) {
return 0;
}
return common::visit(
common::visitors{
[&](const SubprogramDetails &sd) {
return sd.isFunction() ? sd.result().CorankImpl(depth) : 0;
},
[](const GenericDetails &) { return 0; },
[&](const ProcEntityDetails &ped) {
const Symbol *iface{ped.procInterface()};
return iface ? iface->CorankImpl(depth) : 0;
},
[&](const UseDetails &x) { return x.symbol().CorankImpl(depth); },
[&](const HostAssocDetails &x) {
return x.symbol().CorankImpl(depth);
},
[](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
[](const AssocEntityDetails &aed) {
return aed.expr() ? aed.expr()->Corank() : 0;
},
[](const auto &) { return 0; },
},
details_);
}
template <std::size_t> friend class Symbols;
template <class, std::size_t> friend class std::array;
};
Expand Down
15 changes: 7 additions & 8 deletions flang/lib/Evaluate/characteristics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,15 +227,14 @@ void TypeAndShape::AcquireAttrs(const semantics::Symbol &symbol) {
} else if (semantics::IsAssumedSizeArray(symbol)) {
attrs_.set(Attr::AssumedSize);
}
if (int n{GetCorank(symbol)}) {
corank_ = n;
attrs_.set(Attr::Coarray);
}
if (const auto *object{
symbol.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()}) {
corank_ = object->coshape().Rank();
if (object->IsAssumedRank()) {
attrs_.set(Attr::AssumedRank);
}
if (object->IsCoarray()) {
attrs_.set(Attr::Coarray);
}
symbol.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()};
object && object->IsAssumedRank()) {
attrs_.set(Attr::AssumedRank);
}
}

Expand Down
12 changes: 12 additions & 0 deletions flang/lib/Evaluate/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ template <typename A> int ExpressionBase<A>::Rank() const {
derived().u);
}

template <typename A> int ExpressionBase<A>::Corank() const {
return common::visit(
[](const auto &x) {
if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
return 0;
} else {
return x.Corank();
}
},
derived().u);
}

DynamicType Parentheses<SomeDerived>::GetType() const {
return left().GetType().value();
}
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{{"coarray", AnyData, Rank::coarray}, RequiredDIM, OptionalTEAM},
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
{"this_image", {{"coarray", AnyData, Rank::coarray}, OptionalTEAM},
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
DefaultInt, Rank::vector, IntrinsicClass::transformationalFunction},
{"this_image", {OptionalTEAM}, DefaultInt, Rank::scalar,
IntrinsicClass::transformationalFunction},
{"tiny",
Expand Down
9 changes: 9 additions & 0 deletions flang/lib/Evaluate/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,10 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
if (!call.arguments().empty()) {
return (*this)(call.arguments()[0]);
}
} else if (intrinsic->name == "lcobound" || intrinsic->name == "ucobound") {
if (call.arguments().size() == 3 && !call.arguments().at(1).has_value()) {
return Shape(1, ExtentExpr{GetCorank(call.arguments().at(0))});
}
} else if (intrinsic->name == "matmul") {
if (call.arguments().size() == 2) {
if (auto ashape{(*this)(call.arguments()[0])}) {
Expand Down Expand Up @@ -1076,6 +1080,11 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
}
}
}
} else if (intrinsic->name == "this_image") {
if (call.arguments().size() == 2) {
// THIS_IMAGE(coarray, no DIM, [TEAM])
return Shape(1, ExtentExpr{GetCorank(call.arguments().at(0))});
}
} else if (intrinsic->name == "transpose") {
if (call.arguments().size() >= 1) {
if (auto shape{(*this)(call.arguments().at(0))}) {
Expand Down
8 changes: 2 additions & 6 deletions flang/lib/Evaluate/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,13 +906,9 @@ bool IsAssumedRank(const ActualArgument &arg) {
}
}

bool IsCoarray(const ActualArgument &arg) {
int GetCorank(const ActualArgument &arg) {
const auto *expr{arg.UnwrapExpr()};
return expr && IsCoarray(*expr);
}

bool IsCoarray(const Symbol &symbol) {
return GetAssociationRoot(symbol).Corank() > 0;
return GetCorank(*expr);
}

bool IsProcedureDesignator(const Expr<SomeType> &expr) {
Expand Down
Loading
Loading