source: src/SynTree/GcTracer.h@ 6fa409e

new-env
Last change on this file since 6fa409e was d318a18, checked in by Aaron Moss <a3moss@…>, 7 years ago

Fix assorted memory bugs with persistent-array environment

  • Property mode set to 100644
File size: 5.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// GcTracer.h --
8//
9// Author : Aaron B. Moss
10// Created On : Thu Mar 15 14:47:00 2018
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Thu Mar 15 14:47:00 2018
13// Update Count : 1
14//
15
16#pragma once
17
18#include <list>
19
20#include "BaseSyntaxNode.h"
21#include "Expression.h"
22#include "Label.h"
23#include "Type.h"
24
25#include "Common/GC.h"
26#include "Common/PassVisitor.h"
27#include "ResolvExpr/TypeEnvironment.h"
28
29/// Implements `trace` method for syntax nodes
30class GcTracer final : public WithShortCircuiting, public WithVisitorRef<GcTracer> {
31 const GC& gc;
32
33public:
34 GcTracer( const GC& gc ) : gc(gc) {}
35
36 template<typename... Args>
37 void traceAll(Args&... args) { ::traceAll(gc, args...); }
38
39 // mark node and children
40
41 void previsit( BaseSyntaxNode * node ) {
42 // skip tree if already seen
43 if ( node->mark == gc.mark ) {
44 visit_children = false;
45 return;
46 }
47
48 // mark node
49 node->mark = gc.mark;
50 }
51
52 // add visits left out by PassVisitor
53
54 void postvisit( Constant* con ) {
55 maybeAccept( con->get_type(), *visitor );
56 }
57
58 void postvisit( AggregateDecl* decl ) {
59 acceptAll( decl->attributes, *visitor );
60 }
61
62 void postvisit( DeclarationWithType* decl ) {
63 maybeAccept( decl->asmName, *visitor );
64 }
65
66private:
67 void visit( InferredParams& inferParams ) {
68 for ( auto& entry : inferParams ) {
69 maybeAccept( entry.second.actualType, *visitor );
70 maybeAccept( entry.second.formalType, *visitor );
71 maybeAccept( entry.second.expr, *visitor );
72 visit( *entry.second.inferParams );
73 }
74 }
75
76public:
77 void postvisit( Expression* expr ) {
78 maybeAccept( expr->env, *visitor );
79 visit( expr->inferParams );
80 }
81
82 void postvisit( OffsetofExpr* expr ) {
83 postvisit( static_cast<Expression*>(expr) );
84 maybeAccept( expr->member, *visitor );
85 }
86
87 void postvisit( UniqueExpr* expr ) {
88 postvisit( static_cast<Expression*>(expr) );
89 maybeAccept( expr->object, *visitor );
90 maybeAccept( expr->var, *visitor );
91 }
92
93 void postvisit( UntypedExpr* expr ) {
94 postvisit( static_cast<Expression*>(expr) );
95 maybeAccept( expr->function, *visitor );
96 }
97
98 void postvisit( VariableExpr* expr ) {
99 postvisit( static_cast<Expression*>(expr) );
100 maybeAccept( expr->var, *visitor ); // not in PassVisitor because it causes cycle
101 }
102
103private:
104 void visit( Label& lbl ) {
105 acceptAll( lbl.get_attributes(), *visitor );
106 // maybeAccept( lbl.get_statement(), *visitor ); // introduces infinite loop in tracer
107 }
108
109public:
110 void postvisit( Statement* stmt ) {
111 for ( Label& l : stmt->labels ) {
112 visit( l );
113 }
114 }
115
116 void postvisit( BranchStmt* stmt ) {
117 postvisit( static_cast<Statement*>(stmt) );
118 visit( stmt->target );
119 maybeAccept( stmt->computedTarget, *visitor );
120 }
121
122 void postvisit( Type* type ) {
123 acceptAll( type->attributes, *visitor );
124 }
125
126 void postvisit( EnumInstType* type ) {
127 postvisit( static_cast<Type*>(type) );
128 maybeAccept( type->baseEnum, *visitor );
129 }
130
131 void postvisit( PointerType* type ) {
132 postvisit( static_cast<Type*>(type) );
133 maybeAccept( type->dimension, *visitor );
134 }
135
136 void postvisit( StructInstType* type ) {
137 postvisit( static_cast<Type*>(type) );
138 maybeAccept( type->baseStruct, *visitor );
139 }
140
141 void postvisit( TraitInstType* type ) {
142 postvisit( static_cast<Type*>(type) );
143 maybeAccept( type->baseTrait, *visitor );
144 }
145
146 void postvisit( TypeInstType* type ) {
147 postvisit( static_cast<Type*>(type) );
148 maybeAccept( type->baseType, *visitor );
149 }
150
151 void postvisit( UnionInstType* type ) {
152 postvisit( static_cast<Type*>(type) );
153 maybeAccept( type->baseUnion, *visitor );
154 }
155
156private:
157 void visit( const ResolvExpr::TypeEnvironment::Classes* c ) {
158 typedef ResolvExpr::TypeEnvironment::Classes C;
159 // trace all parent classes, short-circuiting at one traced
160 while ( gc.notrace_mark( c ) && c->get_mode() != C::BASE ) { c = c->get_base(); }
161 }
162
163 void visit( const ResolvExpr::TypeEnvironment::Bindings* b ) {
164 typedef ResolvExpr::TypeEnvironment::Bindings B;
165
166 while ( true ) {
167 if ( ! gc.notrace_mark( b ) ) return; // short-circuit if already traced
168
169 if ( b->get_mode() == B::BASE ) break; // break if this is a base map
170
171 if ( b->get_mode() != B::REM ) { // trace bound intermediate elements
172 maybeAccept( b->get_val().type, *visitor );
173 }
174
175 b = b->get_base();
176 }
177
178 // trace bound elements in base binding
179 b->for_each( [&](interned_string, const ResolvExpr::BoundType& bound) {
180 maybeAccept( bound.type, *visitor ); // trace bound elements
181 } );
182 }
183
184public:
185 void visit( const ResolvExpr::TypeEnvironment& env ) {
186 visit( env.classes );
187 visit( env.bindings );
188 }
189};
190
191/// Traces entire translation unit recursively
192static inline const GC& operator<< ( const GC& gc, const std::list<Declaration*>& translationUnit ) {
193 PassVisitor<GcTracer> tracer{ gc };
194 acceptAll( const_cast<std::list<Declaration*>&>( translationUnit ), tracer );
195 return gc;
196}
197
198// Local Variables: //
199// tab-width: 4 //
200// mode: c++ //
201// compile-command: "make install" //
202// End: //
Note: See TracBrowser for help on using the repository browser.