2019-03-05 21:28:08 +01:00
|
|
|
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
2018-09-19 23:26:02 +02:00
|
|
|
//
|
|
|
|
// 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 "canonicalize-do.h"
|
|
|
|
#include "../parser/parse-tree-visitor.h"
|
|
|
|
|
2018-09-21 20:12:02 +02:00
|
|
|
namespace Fortran::parser {
|
2018-09-19 23:26:02 +02:00
|
|
|
|
|
|
|
class CanonicalizationOfDoLoops {
|
2018-10-05 22:59:43 +02:00
|
|
|
struct LabelInfo {
|
|
|
|
Block::iterator iter;
|
|
|
|
Label label;
|
|
|
|
};
|
|
|
|
|
2018-09-19 23:26:02 +02:00
|
|
|
public:
|
|
|
|
template<typename T> bool Pre(T &) { return true; }
|
|
|
|
template<typename T> void Post(T &) {}
|
2018-10-05 22:59:43 +02:00
|
|
|
void Post(Block &block) {
|
|
|
|
std::vector<LabelInfo> stack;
|
|
|
|
for (auto i{block.begin()}, end{block.end()}; i != end; ++i) {
|
|
|
|
if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) {
|
|
|
|
std::visit(
|
2018-11-29 18:27:34 +01:00
|
|
|
common::visitors{
|
|
|
|
[](auto &) {},
|
2018-10-05 22:59:43 +02:00
|
|
|
[&](Statement<common::Indirection<LabelDoStmt>> &labelDoStmt) {
|
2019-03-05 21:28:08 +01:00
|
|
|
auto &label{std::get<Label>(labelDoStmt.statement.value().t)};
|
2018-10-05 22:59:43 +02:00
|
|
|
stack.push_back(LabelInfo{i, label});
|
|
|
|
},
|
|
|
|
[&](Statement<common::Indirection<EndDoStmt>> &endDoStmt) {
|
|
|
|
CanonicalizeIfMatch(block, stack, i, endDoStmt);
|
|
|
|
},
|
|
|
|
[&](Statement<ActionStmt> &actionStmt) {
|
|
|
|
CanonicalizeIfMatch(block, stack, i, actionStmt);
|
2018-11-29 18:27:34 +01:00
|
|
|
},
|
|
|
|
},
|
2018-10-05 22:59:43 +02:00
|
|
|
executableConstruct->u);
|
2018-09-21 17:22:41 +02:00
|
|
|
}
|
2018-09-19 23:26:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-10-05 22:59:43 +02:00
|
|
|
template<typename T>
|
|
|
|
void CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack,
|
|
|
|
Block::iterator &i, Statement<T> &statement) {
|
|
|
|
if (!stack.empty() && statement.label.has_value() &&
|
|
|
|
stack.back().label == *statement.label) {
|
|
|
|
auto currentLabel{stack.back().label};
|
|
|
|
if constexpr (std::is_same_v<T, common::Indirection<EndDoStmt>>) {
|
|
|
|
std::get<ExecutableConstruct>(i->u).u = Statement<ActionStmt>{
|
|
|
|
std::optional<Label>{currentLabel}, ContinueStmt{}};
|
2018-10-04 18:25:58 +02:00
|
|
|
}
|
2018-10-05 22:59:43 +02:00
|
|
|
auto next{++i};
|
|
|
|
do {
|
|
|
|
Block block;
|
|
|
|
auto doLoop{stack.back().iter};
|
2018-10-11 01:52:06 +02:00
|
|
|
auto originalSource{
|
|
|
|
std::get<Statement<common::Indirection<LabelDoStmt>>>(
|
|
|
|
std::get<ExecutableConstruct>(doLoop->u).u)
|
|
|
|
.source};
|
2018-10-05 22:59:43 +02:00
|
|
|
block.splice(block.begin(), originalBlock, ++stack.back().iter, next);
|
2018-10-11 01:52:06 +02:00
|
|
|
Statement<NonLabelDoStmt> nonLabelDoStmt{std::optional<Label>{},
|
|
|
|
NonLabelDoStmt{std::make_tuple(std::optional<Name>{},
|
|
|
|
std::move(std::get<std::optional<LoopControl>>(
|
|
|
|
std::get<Statement<common::Indirection<LabelDoStmt>>>(
|
|
|
|
std::get<ExecutableConstruct>(doLoop->u).u)
|
2019-03-05 21:28:08 +01:00
|
|
|
.statement.value()
|
|
|
|
.t)))}};
|
2018-10-11 01:52:06 +02:00
|
|
|
nonLabelDoStmt.source = originalSource;
|
|
|
|
std::get<ExecutableConstruct>(doLoop->u).u =
|
|
|
|
common::Indirection<DoConstruct>{
|
|
|
|
std::make_tuple(std::move(nonLabelDoStmt), std::move(block),
|
|
|
|
Statement<EndDoStmt>{std::optional<Label>{},
|
|
|
|
EndDoStmt{std::optional<Name>{}}})};
|
2018-10-05 22:59:43 +02:00
|
|
|
stack.pop_back();
|
|
|
|
} while (!stack.empty() && stack.back().label == currentLabel);
|
|
|
|
i = --next;
|
|
|
|
}
|
2018-09-19 23:26:02 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-09-21 20:12:02 +02:00
|
|
|
void CanonicalizeDo(Program &program) {
|
2018-10-05 22:59:43 +02:00
|
|
|
CanonicalizationOfDoLoops canonicalizationOfDoLoops;
|
2018-09-21 20:12:02 +02:00
|
|
|
Walk(program, canonicalizationOfDoLoops);
|
2018-09-19 23:26:02 +02:00
|
|
|
}
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|