[flang-commits] [flang] [flang] Implement !DIR$ VECTOR ALWAYS (PR #93830)
Kiran Chandramohan via flang-commits
flang-commits at lists.llvm.org
Fri Jun 7 17:36:40 PDT 2024
================
@@ -0,0 +1,122 @@
+//===-- lib/Semantics/check-directives.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "canonicalize-directives.h"
+#include "flang/Parser/parse-tree-visitor.h"
+
+namespace Fortran::semantics {
+
+using namespace parser::literals;
+
+// Check that directives are associated with the correct constructs
+class CanonicalizationOfDirectives {
+public:
+ CanonicalizationOfDirectives(parser::Messages &messages)
+ : messages_{messages} {}
+
+ template <typename T> bool Pre(T &) { return true; }
+ template <typename T> void Post(T &) {}
+
+ // Move directives that must appear in the Execution part out of the
+ // Specification part.
+ void Post(parser::SpecificationPart &spec);
+ bool Pre(parser::ExecutionPart &x);
+
+ // Ensure that directives associated with constructs appear accompanying the
+ // construct.
+ void Post(parser::Block &block);
+
+private:
+ // Ensure that loop directives appear immediately before a loop.
+ void CheckLoopDirective(parser::CompilerDirective &dir, parser::Block &block,
+ std::list<parser::ExecutionPartConstruct>::iterator it);
+
+ parser::Messages &messages_;
+
+ // Directives to be moved to the Execution part from the Specification part.
+ std::list<common::Indirection<parser::CompilerDirective>>
+ directivesToConvert_;
+};
+
+bool CanonicalizeDirectives(
+ parser::Messages &messages, parser::Program &program) {
+ CanonicalizationOfDirectives dirs{messages};
+ Walk(program, dirs);
+ return !messages.AnyFatalError();
+}
+
+static bool IsExecutionDirective(const parser::CompilerDirective &dir) {
+ return std::holds_alternative<parser::CompilerDirective::VectorAlways>(dir.u);
+}
+
+void CanonicalizationOfDirectives::Post(parser::SpecificationPart &spec) {
+ auto &list{
+ std::get<std::list<common::Indirection<parser::CompilerDirective>>>(
+ spec.t)};
+ for (auto it{list.begin()}; it != list.end();) {
+ if (IsExecutionDirective(it->value())) {
+ directivesToConvert_.emplace_back(std::move(*it));
+ it = list.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+bool CanonicalizationOfDirectives::Pre(parser::ExecutionPart &x) {
+ auto origFirst{x.v.begin()};
+ for (auto &dir : directivesToConvert_) {
+ x.v.insert(origFirst,
+ parser::ExecutionPartConstruct{
+ parser::ExecutableConstruct{std::move(dir)}});
+ }
+
+ directivesToConvert_.clear();
+ return true;
+}
+
+template <typename T> T *GetConstructIf(parser::ExecutionPartConstruct &x) {
+ if (auto *y{std::get_if<parser::ExecutableConstruct>(&x.u)}) {
+ if (auto *z{std::get_if<common::Indirection<T>>(&y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
+void CanonicalizationOfDirectives::CheckLoopDirective(
+ parser::CompilerDirective &dir, parser::Block &block,
+ std::list<parser::ExecutionPartConstruct>::iterator it) {
+
+ // Skip over this and other compiler directives
+ while (GetConstructIf<parser::CompilerDirective>(*it)) {
+ ++it;
+ }
+
+ if (it == block.end() || !GetConstructIf<parser::DoConstruct>(*it)) {
+ std::string s{parser::ToUpperCaseLetters(dir.source.ToString())};
+ s.pop_back(); // Remove trailing newline from source string
+ messages_.Say(
+ dir.source, "A DO loop must follow the %s directive"_err_en_US, s);
+ }
+}
+
+void CanonicalizationOfDirectives::Post(parser::Block &block) {
+ for (auto it = block.begin(); it != block.end(); ++it) {
----------------
kiranchandramohan wrote:
Nit: braced initialization
https://github.com/llvm/llvm-project/pull/93830
More information about the flang-commits
mailing list