source: src/SynTree/GcTracer.h @ d318a18

new-env
Last change on this file since d318a18 was d318a18, checked in by Aaron Moss <a3moss@…>, 6 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.