[MemProf] Templatize CallStackRadixTreeBuilder (NFC) (#117014)
[llvm-project.git] / flang / lib / Semantics / unparse-with-symbols.cpp
blob02afb89ae57fafd44269808c1fb225c6d90869d9
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-exception
6 //
7 //===----------------------------------------------------------------------===//
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/symbol.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <map>
17 #include <set>
19 namespace Fortran::semantics {
21 // Walk the parse tree and collection information about which statements
22 // reference symbols. Then PrintSymbols outputs information by statement.
23 // The first reference to a symbol is treated as its definition and more
24 // information is included.
25 class SymbolDumpVisitor {
26 public:
27 // Write out symbols referenced at this statement.
28 void PrintSymbols(const parser::CharBlock &, llvm::raw_ostream &, int);
30 template <typename T> bool Pre(const T &) { return true; }
31 template <typename T> void Post(const T &) {}
32 template <typename T> bool Pre(const parser::Statement<T> &stmt) {
33 currStmt_ = stmt.source;
34 return true;
36 template <typename T> void Post(const parser::Statement<T> &) {
37 currStmt_ = std::nullopt;
39 bool Pre(const parser::AccClause &clause) {
40 currStmt_ = clause.source;
41 return true;
43 void Post(const parser::AccClause &) { currStmt_ = std::nullopt; }
44 bool Pre(const parser::OmpClause &clause) {
45 currStmt_ = clause.source;
46 return true;
48 void Post(const parser::OmpClause &) { currStmt_ = std::nullopt; }
49 bool Pre(const parser::OpenMPThreadprivate &dir) {
50 currStmt_ = dir.source;
51 return true;
53 void Post(const parser::OpenMPThreadprivate &) { currStmt_ = std::nullopt; }
54 void Post(const parser::Name &name);
56 bool Pre(const parser::OpenMPDeclareMapperConstruct &x) {
57 currStmt_ = x.source;
58 return true;
60 void Post(const parser::OpenMPDeclareMapperConstruct &) {
61 currStmt_ = std::nullopt;
64 private:
65 std::optional<SourceName> currStmt_; // current statement we are processing
66 std::multimap<const char *, const Symbol *> symbols_; // location to symbol
67 std::set<const Symbol *> symbolsDefined_; // symbols that have been processed
68 void Indent(llvm::raw_ostream &, int) const;
71 void SymbolDumpVisitor::PrintSymbols(
72 const parser::CharBlock &location, llvm::raw_ostream &out, int indent) {
73 std::set<const Symbol *> done; // prevent duplicates on this line
74 auto range{symbols_.equal_range(location.begin())};
75 for (auto it{range.first}; it != range.second; ++it) {
76 const auto *symbol{it->second};
77 if (done.insert(symbol).second) {
78 bool firstTime{symbolsDefined_.insert(symbol).second};
79 Indent(out, indent);
80 out << '!' << (firstTime ? "DEF"s : "REF"s) << ": ";
81 DumpForUnparse(out, *symbol, firstTime);
82 out << '\n';
87 void SymbolDumpVisitor::Indent(llvm::raw_ostream &out, int indent) const {
88 for (int i{0}; i < indent; ++i) {
89 out << ' ';
93 void SymbolDumpVisitor::Post(const parser::Name &name) {
94 if (const auto *symbol{name.symbol}) {
95 if (!symbol->has<MiscDetails>()) {
96 symbols_.emplace(currStmt_.value().begin(), symbol);
101 void UnparseWithSymbols(llvm::raw_ostream &out, const parser::Program &program,
102 parser::Encoding encoding) {
103 SymbolDumpVisitor visitor;
104 parser::Walk(program, visitor);
105 parser::preStatementType preStatement{
106 [&](const parser::CharBlock &location, llvm::raw_ostream &out,
107 int indent) { visitor.PrintSymbols(location, out, indent); }};
108 parser::Unparse(out, program, encoding, false, true, &preStatement);
111 // UnparseWithModules()
113 class UsedModuleVisitor {
114 public:
115 UnorderedSymbolSet &modulesUsed() { return modulesUsed_; }
116 UnorderedSymbolSet &modulesDefined() { return modulesDefined_; }
117 template <typename T> bool Pre(const T &) { return true; }
118 template <typename T> void Post(const T &) {}
119 void Post(const parser::ModuleStmt &module) {
120 if (module.v.symbol) {
121 modulesDefined_.insert(*module.v.symbol);
124 void Post(const parser::UseStmt &use) {
125 if (use.moduleName.symbol) {
126 modulesUsed_.insert(*use.moduleName.symbol);
130 private:
131 UnorderedSymbolSet modulesUsed_;
132 UnorderedSymbolSet modulesDefined_;
135 void UnparseWithModules(llvm::raw_ostream &out, SemanticsContext &context,
136 const parser::Program &program, parser::Encoding encoding) {
137 UsedModuleVisitor visitor;
138 parser::Walk(program, visitor);
139 UnorderedSymbolSet nonIntrinsicModulesWritten{
140 std::move(visitor.modulesDefined())};
141 ModFileWriter writer{context};
142 for (SymbolRef moduleRef : visitor.modulesUsed()) {
143 writer.WriteClosure(out, *moduleRef, nonIntrinsicModulesWritten);
145 parser::Unparse(out, program, encoding, false, true);
147 } // namespace Fortran::semantics