User Guide
perf_visitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \file
12  * \brief \copybrief nmodl::visitor::PerfVisitor
13  */
14 
15 #include <map>
16 #include <set>
17 #include <stack>
18 
19 #include "printer/decl.hpp"
20 #include "symtab/decl.hpp"
21 #include "utils/perf_stat.hpp"
22 #include "visitors/ast_visitor.hpp"
23 
24 
25 namespace nmodl {
26 namespace visitor {
27 
28 /**
29  * \addtogroup visitor_classes
30  * \{
31  */
32 
33 /**
34  * \class PerfVisitor
35  * \brief %Visitor for measuring performance related information
36  *
37  * This visitor used to visit the ast and associated symbol tables
38  * to measure the performance of every block in nmodl file. For
39  * every symbol in associated symbol table, read/write count
40  * is updated which will be used during code generation (to select
41  * memory types). Certain statements like useion, valence etc.
42  * are not executed in the translated C code and hence need to
43  * be skipped (i.e. without visiting children). Note that this
44  * pass must be run after symbol table generation pass.
45  *
46  * \todo
47  * - To measure the performance of statements like if, elseif
48  * and else, we have to find maximum performance from if,elseif,else
49  * and then use it to calculate total performance. In the current
50  * implementation we are doing sum of all blocks. We need to override
51  * IfStatement (which has all sub-blocks) and get maximum performance
52  * of all statements recursively.
53  *
54  * - In order to avoid empty implementations and checking
55  * start_measurement, there should be "empty" ast visitor from
56  * which PerfVisitor should be inherited.
57  */
59  private:
60  /// symbol table of current block being visited
62 
63  /// performance stats of all blocks being visited
64  /// in recursive chain
65  std::stack<utils::PerfStat> blocks_perf;
66 
67  /// total performance of mod file
69 
70  /// performance of current block
72 
73  /// performance of current all childrens
74  std::stack<utils::PerfStat> children_blocks_perf;
75 
76  /// whether to measure performance for current block
77  bool start_measurement = false;
78 
79  /// true while visiting lhs of binary expression
80  /// (to count write operations)
82 
83  /// whether function call is being visited
84  bool under_function_call = false;
85 
86  /// whether solve block is being visited
87  bool under_solve_block = false;
88 
89  /// whether net receive block is being visited
91 
92  /// to print to json file
93  std::unique_ptr<printer::JSONPrinter> printer;
94 
95  /// if not json, all goes to string
96  std::stringstream stream;
97 
98  /// count of per channel instance variables
100 
101  /// subset of instance variables which are constant
103 
104  /// subset of instance variables which are localized
106 
107  /// count of global variables
109 
110  /// subset of global variables which are constant
112 
113  /// subset of global variables which are localized
115 
116  /// count of state variables
118 
119  /// count of pointer / bbcorepointer variables
121 
122  /// count of RANDOM variables
124 
125  /// keys used in map to track var usage
126  std::string const_memr_key = "cm_r_u";
127  std::string const_memw_key = "cm_w_u";
128  std::string global_memr_key = "gm_r_u";
129  std::string global_memw_key = "gm_w_u";
130 
131  /// map of variables to count unique read-writes
132  std::map<std::string, std::set<std::string>> var_usage = {{const_memr_key, {}},
133  {const_memw_key, {}},
134  {global_memr_key, {}},
135  {global_memw_key, {}}};
136 
137  void update_memory_ops(const std::string& name);
138 
139  bool symbol_to_skip(const std::shared_ptr<symtab::Symbol>& symbol) const;
140 
141  static bool is_local_variable(const std::shared_ptr<symtab::Symbol>& symbol);
142 
143  static bool is_constant_variable(const std::shared_ptr<symtab::Symbol>& symbol);
144 
145  void count_variables();
146 
147  void measure_performance(const ast::Ast& node);
148 
149  void print_memory_usage();
150 
151  void add_perf_to_printer(const utils::PerfStat& perf) const;
152 
153  public:
154  PerfVisitor() = default;
155 
156  explicit PerfVisitor(const std::string& filename);
157 
158  void compact_json(bool flag);
159 
160  const utils::PerfStat& get_total_perfstat() const noexcept {
161  return total_perf;
162  }
163 
164  int get_instance_variable_count() const noexcept {
165  return num_instance_variables;
166  }
167 
168  int get_const_instance_variable_count() const noexcept {
170  }
171 
172  int get_const_global_variable_count() const noexcept {
174  }
175 
176  int get_global_variable_count() const noexcept {
177  return num_global_variables;
178  }
179 
180  int get_state_variable_count() const noexcept {
181  return num_state_variables;
182  }
183 
184  void visit_binary_expression(const ast::BinaryExpression& node) override;
185 
186  void visit_function_call(const ast::FunctionCall& node) override;
187 
188  void visit_name(const ast::Name& node) override;
189 
190  void visit_prime_name(const ast::PrimeName& node) override;
191 
192  void visit_solve_block(const ast::SolveBlock& node) override;
193 
194  void visit_statement_block(const ast::StatementBlock& node) override;
195 
196  void visit_unary_expression(const ast::UnaryExpression& node) override;
197 
198  void visit_if_statement(const ast::IfStatement& node) override;
199 
200  void visit_else_if_statement(const ast::ElseIfStatement& node) override;
201 
202  void visit_program(const ast::Program& node) override;
203 
204  /// skip initial block under net_receive block
205  void visit_initial_block(const ast::InitialBlock& node) override;
206 
207  void visit_constructor_block(const ast::ConstructorBlock& node) override;
208 
209  void visit_destructor_block(const ast::DestructorBlock& node) override;
210 
211  void visit_derivative_block(const ast::DerivativeBlock& node) override;
212 
213  void visit_linear_block(const ast::LinearBlock& node) override;
214 
215  void visit_non_linear_block(const ast::NonLinearBlock& node) override;
216 
217  void visit_discrete_block(const ast::DiscreteBlock& node) override;
218 
219  void visit_function_table_block(const ast::FunctionTableBlock& node) override;
220 
221  void visit_function_block(const ast::FunctionBlock& node) override;
222 
223  void visit_procedure_block(const ast::ProcedureBlock& node) override;
224 
225  void visit_net_receive_block(const ast::NetReceiveBlock& node) override;
226 
227  void visit_breakpoint_block(const ast::BreakpointBlock& node) override;
228 
229  void visit_before_block(const ast::BeforeBlock& node) override;
230 
231  void visit_after_block(const ast::AfterBlock& node) override;
232 
233  void visit_ba_block(const ast::BABlock& node) override;
234 
235  void visit_for_netcon(const ast::ForNetcon& node) override;
236 
237  void visit_kinetic_block(const ast::KineticBlock& node) override;
238 
239  /// certain constructs needs to be excluded from usage counting
240  /// and hence need to provide empty implementations
241 
242  void visit_conductance_hint(const ast::ConductanceHint& /*node*/) override {}
243 
244  void visit_local_list_statement(const ast::LocalListStatement& /*node*/) override {}
245 
246  void visit_suffix(const ast::Suffix& /*node*/) override {}
247 
248  void visit_useion(const ast::Useion& /*node*/) override {}
249 
250  void visit_valence(const ast::Valence& /*node*/) override {}
251 
252  void print(std::ostream& ss) const {
253  ss << stream.str();
254  }
255 };
256 
257 /** \} */ // end of visitor_classes
258 
259 } // namespace visitor
260 } // namespace nmodl
nmodl::visitor::PerfVisitor::visit_conductance_hint
void visit_conductance_hint(const ast::ConductanceHint &) override
certain constructs needs to be excluded from usage counting and hence need to provide empty implement...
Definition: perf_visitor.hpp:242
nmodl::visitor::PerfVisitor::visit_before_block
void visit_before_block(const ast::BeforeBlock &node) override
visit node of type ast::BeforeBlock
Definition: perf_visitor.cpp:409
nmodl::ast::BeforeBlock
Represents a BEFORE block in NMODL.
Definition: before_block.hpp:38
nmodl::visitor::PerfVisitor::under_function_call
bool under_function_call
whether function call is being visited
Definition: perf_visitor.hpp:84
nmodl::ast::SolveBlock
TODO.
Definition: solve_block.hpp:38
nmodl::visitor::PerfVisitor::get_const_instance_variable_count
int get_const_instance_variable_count() const noexcept
Definition: perf_visitor.hpp:168
nmodl::ast::BABlock
Represents a block to be executed before or after another block.
Definition: ba_block.hpp:40
nmodl::visitor::PerfVisitor::var_usage
std::map< std::string, std::set< std::string > > var_usage
map of variables to count unique read-writes
Definition: perf_visitor.hpp:132
nmodl::visitor::PerfVisitor::visit_unary_expression
void visit_unary_expression(const ast::UnaryExpression &node) override
visit node of type ast::UnaryExpression
Definition: perf_visitor.cpp:469
nmodl::visitor::PerfVisitor::visit_useion
void visit_useion(const ast::Useion &) override
visit node of type ast::Useion
Definition: perf_visitor.hpp:248
nmodl::visitor::PerfVisitor::get_global_variable_count
int get_global_variable_count() const noexcept
Definition: perf_visitor.hpp:176
nmodl::visitor::ConstAstVisitor
Concrete constant visitor for all AST classes.
Definition: ast_visitor.hpp:166
nmodl::ast::Ast
Base class for all Abstract Syntax Tree node types.
Definition: ast.hpp:69
nmodl::visitor::PerfVisitor::visit_prime_name
void visit_prime_name(const ast::PrimeName &node) override
prime name derived from identifier and hence need to be handled here
Definition: perf_visitor.cpp:208
nmodl::visitor::PerfVisitor::num_state_variables
int num_state_variables
count of state variables
Definition: perf_visitor.hpp:117
nmodl::ast::FunctionBlock
TODO.
Definition: function_block.hpp:39
nmodl::visitor::PerfVisitor::children_blocks_perf
std::stack< utils::PerfStat > children_blocks_perf
performance of current all childrens
Definition: perf_visitor.hpp:74
nmodl::visitor::PerfVisitor::global_memr_key
std::string global_memr_key
Definition: perf_visitor.hpp:128
nmodl::visitor::PerfVisitor::get_instance_variable_count
int get_instance_variable_count() const noexcept
Definition: perf_visitor.hpp:164
nmodl::ast::NetReceiveBlock
TODO.
Definition: net_receive_block.hpp:39
nmodl::ast::FunctionTableBlock
TODO.
Definition: function_table_block.hpp:39
nmodl::visitor::PerfVisitor::is_local_variable
static bool is_local_variable(const std::shared_ptr< symtab::Symbol > &symbol)
Definition: perf_visitor.cpp:510
nmodl::visitor::PerfVisitor::visit_name
void visit_name(const ast::Name &node) override
every variable used is of type name, update counters
Definition: perf_visitor.cpp:202
nmodl::visitor::PerfVisitor::global_memw_key
std::string global_memw_key
Definition: perf_visitor.hpp:129
nmodl::ast::ConductanceHint
Represents CONDUCTANCE statement in NMODL.
Definition: conductance_hint.hpp:46
nmodl::visitor::PerfVisitor::print
void print(std::ostream &ss) const
Definition: perf_visitor.hpp:252
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::visitor::PerfVisitor::visit_after_block
void visit_after_block(const ast::AfterBlock &node) override
visit node of type ast::AfterBlock
Definition: perf_visitor.cpp:413
nmodl::visitor::PerfVisitor::visit_valence
void visit_valence(const ast::Valence &) override
visit node of type ast::Valence
Definition: perf_visitor.hpp:250
nmodl::visitor::PerfVisitor::num_constant_instance_variables
int num_constant_instance_variables
subset of instance variables which are constant
Definition: perf_visitor.hpp:102
nmodl::visitor::PerfVisitor::visit_net_receive_block
void visit_net_receive_block(const ast::NetReceiveBlock &node) override
visit node of type ast::NetReceiveBlock
Definition: perf_visitor.cpp:399
nmodl::visitor::PerfVisitor::update_memory_ops
void update_memory_ops(const std::string &name)
Find symbol in closest scope (up to parent) and update read/write count.
Definition: perf_visitor.cpp:533
nmodl::visitor::PerfVisitor::const_memr_key
std::string const_memr_key
keys used in map to track var usage
Definition: perf_visitor.hpp:126
nmodl::ast::Valence
TODO.
Definition: valence.hpp:38
nmodl::visitor::PerfVisitor::visit_binary_expression
void visit_binary_expression(const ast::BinaryExpression &node) override
count math operations from all binary expressions
Definition: perf_visitor.cpp:34
nmodl::ast::Suffix
Represents SUFFIX statement in NMODL.
Definition: suffix.hpp:38
nmodl::visitor::PerfVisitor::visit_non_linear_block
void visit_non_linear_block(const ast::NonLinearBlock &node) override
visit node of type ast::NonLinearBlock
Definition: perf_visitor.cpp:379
nmodl::ast::ElseIfStatement
TODO.
Definition: else_if_statement.hpp:38
nmodl::visitor::PerfVisitor::visit_statement_block
void visit_statement_block(const ast::StatementBlock &node) override
Blocks like function can have multiple statement blocks and blocks like net receive has nested initia...
Definition: perf_visitor.cpp:433
nmodl::visitor::PerfVisitor::current_symtab
symtab::SymbolTable * current_symtab
symbol table of current block being visited
Definition: perf_visitor.hpp:61
nmodl::visitor::PerfVisitor::visit_function_call
void visit_function_call(const ast::FunctionCall &node) override
count function calls and "most useful" or "commonly used" math functions
Definition: perf_visitor.cpp:175
nmodl::visitor::PerfVisitor::num_instance_variables
int num_instance_variables
count of per channel instance variables
Definition: perf_visitor.hpp:99
nmodl::visitor::PerfVisitor::count_variables
void count_variables()
Definition: perf_visitor.cpp:227
nmodl::visitor::PerfVisitor::visit_procedure_block
void visit_procedure_block(const ast::ProcedureBlock &node) override
visit node of type ast::ProcedureBlock
Definition: perf_visitor.cpp:395
nmodl::ast::InitialBlock
Represents a INITIAL block in the NMODL.
Definition: initial_block.hpp:49
nmodl::visitor::PerfVisitor::PerfVisitor
PerfVisitor()=default
nmodl::visitor::PerfVisitor
Visitor for measuring performance related information
Definition: perf_visitor.hpp:58
nmodl::visitor::PerfVisitor::visit_destructor_block
void visit_destructor_block(const ast::DestructorBlock &node) override
visit node of type ast::DestructorBlock
Definition: perf_visitor.cpp:367
nmodl::visitor::PerfVisitor::visiting_lhs_expression
bool visiting_lhs_expression
true while visiting lhs of binary expression (to count write operations)
Definition: perf_visitor.hpp:81
nmodl::ast::DiscreteBlock
TODO.
Definition: discrete_block.hpp:38
nmodl::visitor::PerfVisitor::compact_json
void compact_json(bool flag)
Definition: perf_visitor.cpp:28
nmodl::visitor::PerfVisitor::printer
std::unique_ptr< printer::JSONPrinter > printer
to print to json file
Definition: perf_visitor.hpp:93
decl.hpp
Forward references of symbols defined in namespace nmodl::printer.
nmodl::ast::LocalListStatement
TODO.
Definition: local_list_statement.hpp:39
nmodl::ast::BreakpointBlock
Represents a BREAKPOINT block in NMODL.
Definition: breakpoint_block.hpp:53
nmodl::visitor::PerfVisitor::visit_program
void visit_program(const ast::Program &node) override
visit node of type ast::Program
Definition: perf_visitor.cpp:334
nmodl::ast::FunctionCall
TODO.
Definition: function_call.hpp:38
nmodl::ast::DestructorBlock
Represents a DESTRUCTOR block in the NMODL.
Definition: destructor_block.hpp:53
nmodl::visitor::PerfVisitor::visit_suffix
void visit_suffix(const ast::Suffix &) override
visit node of type ast::Suffix
Definition: perf_visitor.hpp:246
nmodl::visitor::PerfVisitor::start_measurement
bool start_measurement
whether to measure performance for current block
Definition: perf_visitor.hpp:77
nmodl::ast::ConstructorBlock
Represents a CONSTRUCTOR block in the NMODL.
Definition: constructor_block.hpp:51
nmodl::ast::Useion
Represents USEION statement in NMODL.
Definition: useion.hpp:40
nmodl::visitor::PerfVisitor::visit_solve_block
void visit_solve_block(const ast::SolveBlock &node) override
solve is not a statement but could have associated block and hence could/should not be skipped comple...
Definition: perf_visitor.cpp:463
nmodl::ast::UnaryExpression
TODO.
Definition: unary_expression.hpp:39
nmodl::visitor::PerfVisitor::is_constant_variable
static bool is_constant_variable(const std::shared_ptr< symtab::Symbol > &symbol)
Definition: perf_visitor.cpp:520
nmodl::visitor::PerfVisitor::under_net_receive_block
bool under_net_receive_block
whether net receive block is being visited
Definition: perf_visitor.hpp:90
nmodl::visitor::PerfVisitor::num_localized_global_variables
int num_localized_global_variables
subset of global variables which are localized
Definition: perf_visitor.hpp:114
nmodl::ast::PrimeName
Represents a prime variable (for ODE)
Definition: prime_name.hpp:48
nmodl::ast::DerivativeBlock
Represents DERIVATIVE block in the NMODL.
Definition: derivative_block.hpp:49
nmodl::ast::IfStatement
TODO.
Definition: if_statement.hpp:39
nmodl::symtab::SymbolTable
Represent symbol table for a NMODL block.
Definition: symbol_table.hpp:57
nmodl::visitor::PerfVisitor::visit_for_netcon
void visit_for_netcon(const ast::ForNetcon &node) override
visit node of type ast::ForNetcon
Definition: perf_visitor.cpp:421
nmodl::ast::KineticBlock
TODO.
Definition: kinetic_block.hpp:39
nmodl::visitor::PerfVisitor::visit_discrete_block
void visit_discrete_block(const ast::DiscreteBlock &node) override
visit node of type ast::DiscreteBlock
Definition: perf_visitor.cpp:383
nmodl::visitor::PerfVisitor::visit_constructor_block
void visit_constructor_block(const ast::ConstructorBlock &node) override
visit node of type ast::ConstructorBlock
Definition: perf_visitor.cpp:363
nmodl::visitor::PerfVisitor::visit_if_statement
void visit_if_statement(const ast::IfStatement &node) override
visit node of type ast::IfStatement
Definition: perf_visitor.cpp:213
nmodl::ast::StatementBlock
Represents block encapsulating list of statements.
Definition: statement_block.hpp:53
nmodl::visitor::PerfVisitor::measure_performance
void measure_performance(const ast::Ast &node)
Helper function used by all ast nodes : visit all children recursively and performance stats get adde...
Definition: perf_visitor.cpp:132
nmodl::ast::ForNetcon
TODO.
Definition: for_netcon.hpp:39
nmodl::visitor::PerfVisitor::visit_else_if_statement
void visit_else_if_statement(const ast::ElseIfStatement &node) override
visit node of type ast::ElseIfStatement
Definition: perf_visitor.cpp:220
nmodl::visitor::PerfVisitor::num_pointer_variables
int num_pointer_variables
count of pointer / bbcorepointer variables
Definition: perf_visitor.hpp:120
nmodl::visitor::PerfVisitor::blocks_perf
std::stack< utils::PerfStat > blocks_perf
performance stats of all blocks being visited in recursive chain
Definition: perf_visitor.hpp:65
nmodl::ast::LinearBlock
Represents LINEAR block in the NMODL.
Definition: linear_block.hpp:53
nmodl::visitor::PerfVisitor::num_global_variables
int num_global_variables
count of global variables
Definition: perf_visitor.hpp:108
nmodl::visitor::PerfVisitor::num_localized_instance_variables
int num_localized_instance_variables
subset of instance variables which are localized
Definition: perf_visitor.hpp:105
nmodl::ast::ProcedureBlock
TODO.
Definition: procedure_block.hpp:39
nmodl::ast::NonLinearBlock
Represents NONLINEAR block in the NMODL.
Definition: non_linear_block.hpp:50
nmodl::visitor::PerfVisitor::under_solve_block
bool under_solve_block
whether solve block is being visited
Definition: perf_visitor.hpp:87
nmodl::visitor::PerfVisitor::stream
std::stringstream stream
if not json, all goes to string
Definition: perf_visitor.hpp:96
nmodl::visitor::PerfVisitor::current_block_perf
utils::PerfStat current_block_perf
performance of current block
Definition: perf_visitor.hpp:71
nmodl::visitor::PerfVisitor::visit_ba_block
void visit_ba_block(const ast::BABlock &node) override
visit node of type ast::BABlock
Definition: perf_visitor.cpp:417
nmodl::visitor::PerfVisitor::visit_linear_block
void visit_linear_block(const ast::LinearBlock &node) override
visit node of type ast::LinearBlock
Definition: perf_visitor.cpp:375
nmodl::visitor::PerfVisitor::symbol_to_skip
bool symbol_to_skip(const std::shared_ptr< symtab::Symbol > &symbol) const
Certain statements / symbols needs extra check while measuring read/write operations.
Definition: perf_visitor.cpp:494
nmodl::visitor::PerfVisitor::visit_breakpoint_block
void visit_breakpoint_block(const ast::BreakpointBlock &node) override
visit node of type ast::BreakpointBlock
Definition: perf_visitor.cpp:405
nmodl::visitor::PerfVisitor::total_perf
utils::PerfStat total_perf
total performance of mod file
Definition: perf_visitor.hpp:68
nmodl::visitor::PerfVisitor::get_total_perfstat
const utils::PerfStat & get_total_perfstat() const noexcept
Definition: perf_visitor.hpp:160
nmodl::utils::PerfStat
Helper class to collect performance statistics.
Definition: perf_stat.hpp:36
nmodl::visitor::PerfVisitor::get_const_global_variable_count
int get_const_global_variable_count() const noexcept
Definition: perf_visitor.hpp:172
nmodl::ast::Name
Represents a name.
Definition: name.hpp:44
nmodl::ast::Program
Represents top level AST node for whole NMODL input.
Definition: program.hpp:39
nmodl::visitor::PerfVisitor::visit_function_table_block
void visit_function_table_block(const ast::FunctionTableBlock &node) override
visit node of type ast::FunctionTableBlock
Definition: perf_visitor.cpp:387
nmodl::visitor::PerfVisitor::visit_local_list_statement
void visit_local_list_statement(const ast::LocalListStatement &) override
visit node of type ast::LocalListStatement
Definition: perf_visitor.hpp:244
nmodl::visitor::PerfVisitor::num_constant_global_variables
int num_constant_global_variables
subset of global variables which are constant
Definition: perf_visitor.hpp:111
nmodl::visitor::PerfVisitor::const_memw_key
std::string const_memw_key
Definition: perf_visitor.hpp:127
nmodl::ast::AfterBlock
Represents a AFTER block in NMODL.
Definition: after_block.hpp:51
nmodl::visitor::PerfVisitor::num_random_variables
int num_random_variables
count of RANDOM variables
Definition: perf_visitor.hpp:123
nmodl::visitor::PerfVisitor::get_state_variable_count
int get_state_variable_count() const noexcept
Definition: perf_visitor.hpp:180
nmodl::visitor::PerfVisitor::visit_kinetic_block
void visit_kinetic_block(const ast::KineticBlock &node) override
visit node of type ast::KineticBlock
Definition: perf_visitor.cpp:425
nmodl::visitor::PerfVisitor::print_memory_usage
void print_memory_usage()
Definition: perf_visitor.cpp:287
nmodl::visitor::PerfVisitor::add_perf_to_printer
void add_perf_to_printer(const utils::PerfStat &perf) const
add performance stats to json printer
Definition: perf_visitor.cpp:117
nmodl::ast::BinaryExpression
Represents binary expression in the NMODL.
Definition: binary_expression.hpp:52
perf_stat.hpp
Implement class for performance statistics.
nmodl::visitor::PerfVisitor::visit_initial_block
void visit_initial_block(const ast::InitialBlock &node) override
skip initial block under net_receive block
Definition: perf_visitor.cpp:357
decl.hpp
Forward declarations of symbols in namespace nmodl::symtab.
nmodl::visitor::PerfVisitor::visit_function_block
void visit_function_block(const ast::FunctionBlock &node) override
visit node of type ast::FunctionBlock
Definition: perf_visitor.cpp:391
nmodl::visitor::PerfVisitor::visit_derivative_block
void visit_derivative_block(const ast::DerivativeBlock &node) override
visit node of type ast::DerivativeBlock
Definition: perf_visitor.cpp:371
ast_visitor.hpp
Concrete visitor for all AST classes.