brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · ec5b3ff Raw
185 lines · cpp
1//===-- lib/Semantics/unparse-with-symbols.cpp ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Semantics/unparse-with-symbols.h"10#include "mod-file.h"11#include "flang/Parser/parse-tree-visitor.h"12#include "flang/Parser/parse-tree.h"13#include "flang/Parser/unparse.h"14#include "flang/Semantics/semantics.h"15#include "flang/Semantics/symbol.h"16#include "llvm/Support/raw_ostream.h"17#include <map>18#include <set>19 20namespace Fortran::semantics {21 22// Walk the parse tree and collection information about which statements23// reference symbols. Then PrintSymbols outputs information by statement.24// The first reference to a symbol is treated as its definition and more25// information is included.26class SymbolDumpVisitor {27public:28  // Write out symbols referenced at this statement.29  void PrintSymbols(const parser::CharBlock &, llvm::raw_ostream &, int);30 31  template <typename T> bool Pre(const T &) { return true; }32  template <typename T> void Post(const T &) {}33  template <typename T> bool Pre(const parser::Statement<T> &stmt) {34    currStmt_ = stmt.source;35    return true;36  }37  template <typename T> void Post(const parser::Statement<T> &) {38    currStmt_ = std::nullopt;39  }40  void Post(const parser::Name &name);41 42  bool Pre(const parser::AccClause &clause) {43    currStmt_ = clause.source;44    return true;45  }46  void Post(const parser::AccClause &) { currStmt_ = std::nullopt; }47  bool Pre(const parser::OmpClause &clause) {48    currStmt_ = clause.source;49    return true;50  }51  void Post(const parser::OmpClause &) { currStmt_ = std::nullopt; }52  bool Pre(const parser::OpenMPGroupprivate &dir) {53    currStmt_ = dir.source;54    return true;55  }56  void Post(const parser::OpenMPGroupprivate &) { currStmt_ = std::nullopt; }57  bool Pre(const parser::OpenMPThreadprivate &dir) {58    currStmt_ = dir.source;59    return true;60  }61  void Post(const parser::OpenMPThreadprivate &) { currStmt_ = std::nullopt; }62 63  bool Pre(const parser::OpenMPDeclareMapperConstruct &x) {64    currStmt_ = x.source;65    return true;66  }67  void Post(const parser::OpenMPDeclareMapperConstruct &) {68    currStmt_ = std::nullopt;69  }70 71  bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {72    currStmt_ = x.source;73    return true;74  }75  void Post(const parser::OpenMPDeclareReductionConstruct &) {76    currStmt_ = std::nullopt;77  }78 79  bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {80    currStmt_ = x.source;81    return true;82  }83  void Post(const parser::OpenMPDeclareTargetConstruct &) {84    currStmt_ = std::nullopt;85  }86 87  // Directive arguments can be objects with symbols.88  bool Pre(const parser::OmpBeginDirective &x) {89    currStmt_ = x.source;90    return true;91  }92  void Post(const parser::OmpBeginDirective &) { currStmt_ = std::nullopt; }93 94  bool Pre(const parser::OmpEndDirective &x) {95    currStmt_ = x.source;96    return true;97  }98  void Post(const parser::OmpEndDirective &) { currStmt_ = std::nullopt; }99 100private:101  std::optional<SourceName> currStmt_; // current statement we are processing102  std::multimap<const char *, const Symbol *> symbols_; // location to symbol103  std::set<const Symbol *> symbolsDefined_; // symbols that have been processed104  void Indent(llvm::raw_ostream &, int) const;105};106 107void SymbolDumpVisitor::PrintSymbols(108    const parser::CharBlock &location, llvm::raw_ostream &out, int indent) {109  std::set<const Symbol *> done; // prevent duplicates on this line110  auto range{symbols_.equal_range(location.begin())};111  for (auto it{range.first}; it != range.second; ++it) {112    const auto *symbol{it->second};113    if (done.insert(symbol).second) {114      bool firstTime{symbolsDefined_.insert(symbol).second};115      Indent(out, indent);116      out << '!' << (firstTime ? "DEF"s : "REF"s) << ": ";117      DumpForUnparse(out, *symbol, firstTime);118      out << '\n';119    }120  }121}122 123void SymbolDumpVisitor::Indent(llvm::raw_ostream &out, int indent) const {124  for (int i{0}; i < indent; ++i) {125    out << ' ';126  }127}128 129void SymbolDumpVisitor::Post(const parser::Name &name) {130  if (const auto *symbol{name.symbol}) {131    if (!symbol->has<MiscDetails>()) {132      CHECK(currStmt_.has_value());133      symbols_.emplace(currStmt_.value().begin(), symbol);134    }135  }136}137 138void UnparseWithSymbols(llvm::raw_ostream &out, const parser::Program &program,139    const common::LangOptions &langOpts, parser::Encoding encoding) {140  SymbolDumpVisitor visitor;141  parser::Walk(program, visitor);142  parser::preStatementType preStatement{143      [&](const parser::CharBlock &location, llvm::raw_ostream &out,144          int indent) { visitor.PrintSymbols(location, out, indent); }};145  parser::Unparse(out, program, langOpts, encoding, false, true, &preStatement);146}147 148// UnparseWithModules()149 150class UsedModuleVisitor {151public:152  UnorderedSymbolSet &modulesUsed() { return modulesUsed_; }153  UnorderedSymbolSet &modulesDefined() { return modulesDefined_; }154  template <typename T> bool Pre(const T &) { return true; }155  template <typename T> void Post(const T &) {}156  void Post(const parser::ModuleStmt &module) {157    if (module.v.symbol) {158      modulesDefined_.insert(*module.v.symbol);159    }160  }161  void Post(const parser::UseStmt &use) {162    if (use.moduleName.symbol) {163      modulesUsed_.insert(*use.moduleName.symbol);164    }165  }166 167private:168  UnorderedSymbolSet modulesUsed_;169  UnorderedSymbolSet modulesDefined_;170};171 172void UnparseWithModules(llvm::raw_ostream &out, SemanticsContext &context,173    const parser::Program &program, parser::Encoding encoding) {174  UsedModuleVisitor visitor;175  parser::Walk(program, visitor);176  UnorderedSymbolSet nonIntrinsicModulesWritten{177      std::move(visitor.modulesDefined())};178  ModFileWriter writer{context};179  for (SymbolRef moduleRef : visitor.modulesUsed()) {180    writer.WriteClosure(out, *moduleRef, nonIntrinsicModulesWritten);181  }182  parser::Unparse(out, program, context.langOptions(), encoding, false, true);183}184} // namespace Fortran::semantics185