summaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/tools.cpp')
-rw-r--r--flang/lib/Semantics/tools.cpp329
1 files changed, 0 insertions, 329 deletions
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index bf520d04a50c..d053179448c0 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -17,7 +17,6 @@
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "flang/Support/Fortran.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <set>
@@ -1789,332 +1788,4 @@ bool HadUseError(
}
}
-bool CheckForSymbolMatch(const SomeExpr *lhs, const SomeExpr *rhs) {
- if (lhs && rhs) {
- if (SymbolVector lhsSymbols{evaluate::GetSymbolVector(*lhs)};
- !lhsSymbols.empty()) {
- const Symbol &first{*lhsSymbols.front()};
- for (const Symbol &symbol : evaluate::GetSymbolVector(*rhs)) {
- if (first == symbol) {
- return true;
- }
- }
- }
- }
- return false;
-}
-
-namespace operation {
-template <typename T> //
-SomeExpr asSomeExpr(const T &x) {
- auto copy{x};
- return AsGenericExpr(std::move(copy));
-}
-
-template <bool IgnoreResizingConverts> //
-struct ArgumentExtractor
- : public evaluate::Traverse<ArgumentExtractor<IgnoreResizingConverts>,
- std::pair<operation::Operator, std::vector<SomeExpr>>, false> {
- using Arguments = std::vector<SomeExpr>;
- using Result = std::pair<operation::Operator, Arguments>;
- using Base = evaluate::Traverse<ArgumentExtractor<IgnoreResizingConverts>,
- Result, false>;
- static constexpr auto IgnoreResizes = IgnoreResizingConverts;
- static constexpr auto Logical = common::TypeCategory::Logical;
- ArgumentExtractor() : Base(*this) {}
-
- Result Default() const { return {}; }
-
- using Base::operator();
-
- template <int Kind> //
- Result operator()(
- const evaluate::Constant<evaluate::Type<Logical, Kind>> &x) const {
- if (const auto &val{x.GetScalarValue()}) {
- return val->IsTrue()
- ? std::make_pair(operation::Operator::True, Arguments{})
- : std::make_pair(operation::Operator::False, Arguments{});
- }
- return Default();
- }
-
- template <typename R> //
- Result operator()(const evaluate::FunctionRef<R> &x) const {
- Result result{operation::OperationCode(x.proc()), {}};
- for (size_t i{0}, e{x.arguments().size()}; i != e; ++i) {
- if (auto *e{x.UnwrapArgExpr(i)}) {
- result.second.push_back(*e);
- }
- }
- return result;
- }
-
- template <typename D, typename R, typename... Os>
- Result operator()(const evaluate::Operation<D, R, Os...> &x) const {
- if constexpr (std::is_same_v<D, evaluate::Parentheses<R>>) {
- // Ignore top-level parentheses.
- return (*this)(x.template operand<0>());
- }
- if constexpr (IgnoreResizes &&
- std::is_same_v<D, evaluate::Convert<R, R::category>>) {
- // Ignore conversions within the same category.
- // Atomic operations on int(kind=1) may be implicitly widened
- // to int(kind=4) for example.
- return (*this)(x.template operand<0>());
- } else {
- return std::make_pair(operation::OperationCode(x),
- OperationArgs(x, std::index_sequence_for<Os...>{}));
- }
- }
-
- template <typename T> //
- Result operator()(const evaluate::Designator<T> &x) const {
- return {operation::Operator::Identity, {asSomeExpr(x)}};
- }
-
- template <typename T> //
- Result operator()(const evaluate::Constant<T> &x) const {
- return {operation::Operator::Identity, {asSomeExpr(x)}};
- }
-
- template <typename... Rs> //
- Result Combine(Result &&result, Rs &&...results) const {
- // There shouldn't be any combining needed, since we're stopping the
- // traversal at the top-level operation, but implement one that picks
- // the first non-empty result.
- if constexpr (sizeof...(Rs) == 0) {
- return std::move(result);
- } else {
- if (!result.second.empty()) {
- return std::move(result);
- } else {
- return Combine(std::move(results)...);
- }
- }
- }
-
-private:
- template <typename D, typename R, typename... Os, size_t... Is>
- Arguments OperationArgs(const evaluate::Operation<D, R, Os...> &x,
- std::index_sequence<Is...>) const {
- return Arguments{SomeExpr(x.template operand<Is>())...};
- }
-};
-} // namespace operation
-
-std::string operation::ToString(operation::Operator op) {
- switch (op) {
- case Operator::Unknown:
- return "??";
- case Operator::Add:
- return "+";
- case Operator::And:
- return "AND";
- case Operator::Associated:
- return "ASSOCIATED";
- case Operator::Call:
- return "function-call";
- case Operator::Constant:
- return "constant";
- case Operator::Convert:
- return "type-conversion";
- case Operator::Div:
- return "/";
- case Operator::Eq:
- return "==";
- case Operator::Eqv:
- return "EQV";
- case Operator::False:
- return ".FALSE.";
- case Operator::Ge:
- return ">=";
- case Operator::Gt:
- return ">";
- case Operator::Identity:
- return "identity";
- case Operator::Intrinsic:
- return "intrinsic";
- case Operator::Le:
- return "<=";
- case Operator::Lt:
- return "<";
- case Operator::Max:
- return "MAX";
- case Operator::Min:
- return "MIN";
- case Operator::Mul:
- return "*";
- case Operator::Ne:
- return "/=";
- case Operator::Neqv:
- return "NEQV/EOR";
- case Operator::Not:
- return "NOT";
- case Operator::Or:
- return "OR";
- case Operator::Pow:
- return "**";
- case Operator::Resize:
- return "resize";
- case Operator::Sub:
- return "-";
- case Operator::True:
- return ".TRUE.";
- }
- llvm_unreachable("Unhandler operator");
-}
-
-operation::Operator operation::OperationCode(
- const evaluate::ProcedureDesignator &proc) {
- Operator code = llvm::StringSwitch<Operator>(proc.GetName())
- .Case("associated", Operator::Associated)
- .Case("min", Operator::Min)
- .Case("max", Operator::Max)
- .Case("iand", Operator::And)
- .Case("ior", Operator::Or)
- .Case("ieor", Operator::Neqv)
- .Default(Operator::Call);
- if (code == Operator::Call && proc.GetSpecificIntrinsic()) {
- return Operator::Intrinsic;
- }
- return code;
-}
-
-std::pair<operation::Operator, std::vector<SomeExpr>> GetTopLevelOperation(
- const SomeExpr &expr) {
- return operation::ArgumentExtractor<true>{}(expr);
-}
-
-namespace operation {
-struct ConvertCollector
- : public evaluate::Traverse<ConvertCollector,
- std::pair<MaybeExpr, std::vector<evaluate::DynamicType>>, false> {
- using Result = std::pair<MaybeExpr, std::vector<evaluate::DynamicType>>;
- using Base = evaluate::Traverse<ConvertCollector, Result, false>;
- ConvertCollector() : Base(*this) {}
-
- Result Default() const { return {}; }
-
- using Base::operator();
-
- template <typename T> //
- Result operator()(const evaluate::Designator<T> &x) const {
- return {asSomeExpr(x), {}};
- }
-
- template <typename T> //
- Result operator()(const evaluate::FunctionRef<T> &x) const {
- return {asSomeExpr(x), {}};
- }
-
- template <typename T> //
- Result operator()(const evaluate::Constant<T> &x) const {
- return {asSomeExpr(x), {}};
- }
-
- template <typename D, typename R, typename... Os>
- Result operator()(const evaluate::Operation<D, R, Os...> &x) const {
- if constexpr (std::is_same_v<D, evaluate::Parentheses<R>>) {
- // Ignore parentheses.
- return (*this)(x.template operand<0>());
- } else if constexpr (is_convert_v<D>) {
- // Convert should always have a typed result, so it should be safe to
- // dereference x.GetType().
- return Combine(
- {std::nullopt, {*x.GetType()}}, (*this)(x.template operand<0>()));
- } else if constexpr (is_complex_constructor_v<D>) {
- // This is a conversion iff the imaginary operand is 0.
- if (IsZero(x.template operand<1>())) {
- return Combine(
- {std::nullopt, {*x.GetType()}}, (*this)(x.template operand<0>()));
- } else {
- return {asSomeExpr(x.derived()), {}};
- }
- } else {
- return {asSomeExpr(x.derived()), {}};
- }
- }
-
- template <typename... Rs> //
- Result Combine(Result &&result, Rs &&...results) const {
- Result v(std::move(result));
- auto setValue{[](MaybeExpr &x, MaybeExpr &&y) {
- assert((!x.has_value() || !y.has_value()) && "Multiple designators");
- if (!x.has_value()) {
- x = std::move(y);
- }
- }};
- auto moveAppend{[](auto &accum, auto &&other) {
- for (auto &&s : other) {
- accum.push_back(std::move(s));
- }
- }};
- (setValue(v.first, std::move(results).first), ...);
- (moveAppend(v.second, std::move(results).second), ...);
- return v;
- }
-
-private:
- template <typename T> //
- static bool IsZero(const T &x) {
- return false;
- }
- template <typename T> //
- static bool IsZero(const evaluate::Expr<T> &x) {
- return common::visit([](auto &&s) { return IsZero(s); }, x.u);
- }
- template <typename T> //
- static bool IsZero(const evaluate::Constant<T> &x) {
- if (auto &&maybeScalar{x.GetScalarValue()}) {
- return maybeScalar->IsZero();
- } else {
- return false;
- }
- }
-
- template <typename T> //
- struct is_convert {
- static constexpr bool value{false};
- };
- template <typename T, common::TypeCategory C> //
- struct is_convert<evaluate::Convert<T, C>> {
- static constexpr bool value{true};
- };
- template <int K> //
- struct is_convert<evaluate::ComplexComponent<K>> {
- // Conversion from complex to real.
- static constexpr bool value{true};
- };
- template <typename T> //
- static constexpr bool is_convert_v = is_convert<T>::value;
-
- template <typename T> //
- struct is_complex_constructor {
- static constexpr bool value{false};
- };
- template <int K> //
- struct is_complex_constructor<evaluate::ComplexConstructor<K>> {
- static constexpr bool value{true};
- };
- template <typename T> //
- static constexpr bool is_complex_constructor_v =
- is_complex_constructor<T>::value;
-};
-} // namespace operation
-
-MaybeExpr GetConvertInput(const SomeExpr &x) {
- // This returns SomeExpr(x) when x is a designator/functionref/constant.
- return operation::ConvertCollector{}(x).first;
-}
-
-bool IsSameOrConvertOf(const SomeExpr &expr, const SomeExpr &x) {
- // Check if expr is same as x, or a sequence of Convert operations on x.
- if (expr == x) {
- return true;
- } else if (auto maybe{GetConvertInput(expr)}) {
- return *maybe == x;
- } else {
- return false;
- }
-}
} // namespace Fortran::semantics \ No newline at end of file