|
6 | 6 |
|
7 | 7 | #include "ASTVisitor.h" |
8 | 8 |
|
| 9 | +/** |
| 10 | + * This pass analysis lifetimes of variables by using Life structs with the first statement |
| 11 | + * and the last statement they are used in. |
| 12 | + * It parses stmt by stmt, assigns a lifetime object with the current stmt as start and end |
| 13 | + * upon visiting a declaration and assignes a new end stmt every time a reference to this var is |
| 14 | + * visited |
| 15 | + * - variables declared in a while loop (since all other loop forms are transformed at this point) |
| 16 | + * are always assigned the full lifetime of the while loop body |
| 17 | + */ |
9 | 18 | class ASTLifeTimeAnalysis : public ASTVisitor { |
10 | 19 | DefinitionProvider* m_def_provider = nullptr; |
11 | 20 | NodeStatement* m_current_statement = nullptr; |
@@ -61,6 +70,18 @@ class ASTLifeTimeAnalysis : public ASTVisitor { |
61 | 70 | return m_life_times; |
62 | 71 | } |
63 | 72 |
|
| 73 | + // this is not used in variable reuse because all relevant function parameters are already |
| 74 | + // transformed into assignment statements by parameter transform pass |
| 75 | + std::unordered_map<NodeDataStructure*, Life>& run(NodeFunctionDefinition& def) { |
| 76 | + m_variables_in_while.clear(); |
| 77 | + is_in_while_loop = false; |
| 78 | + m_life_times.clear(); |
| 79 | + m_visited_blocks.clear(); |
| 80 | + m_current_statement = def.body->front(); |
| 81 | + def.accept(*this); |
| 82 | + return m_life_times; |
| 83 | + } |
| 84 | + |
64 | 85 | /// can be called after run() -> deletes all declaration nodes with variables where |
65 | 86 | /// start and end member in Life are the same |
66 | 87 | int remove_unused_local_variables() { |
@@ -101,7 +122,7 @@ class ASTLifeTimeAnalysis : public ASTVisitor { |
101 | 122 |
|
102 | 123 | NodeAST *visit(NodeBlock &node) override { |
103 | 124 | m_visited_blocks.insert(&node); |
104 | | - m_end_of_current_block.push(node.statements.empty() ? nullptr : node.statements.back().get()); |
| 125 | + m_end_of_current_block.push(node.back()); |
105 | 126 | ASTVisitor::visit(node); |
106 | 127 | m_end_of_current_block.pop(); |
107 | 128 | return &node; |
@@ -132,6 +153,17 @@ class ASTLifeTimeAnalysis : public ASTVisitor { |
132 | 153 | return &node; |
133 | 154 | } |
134 | 155 |
|
| 156 | + NodeAST* visit(NodeFunctionParam & node) override { |
| 157 | + node.variable->accept(*this); |
| 158 | + // have to do this extra if-check because function param nodes are also used for |
| 159 | + // foreach key, value |
| 160 | + if (node.variable->is_function_param()) { |
| 161 | + add_lifetime_start(node.variable.get(), m_current_statement); |
| 162 | + } |
| 163 | + if (node.value) node.value->accept(*this); |
| 164 | + return &node; |
| 165 | + } |
| 166 | + |
135 | 167 | NodeAST *visit(NodeArrayRef &node) override { |
136 | 168 | add_lifetime_end(node, m_current_statement); |
137 | 169 | return ASTVisitor::visit(node); |
|
0 commit comments