source: src/Common/PassVisitor.proto.h @ 2a7b3ca

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 2a7b3ca was 2a7b3ca, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

convert InstantiateGeneric? to PassVisitor?, add missing mutate and accept calls to PassVisitor?, add missing ValueGuardPtrs? to PassVisitor::handleStatementList

  • Property mode set to 100644
File size: 6.1 KB
Line 
1#pragma once
2
3template<typename pass_type>
4class PassVisitor;
5
6typedef std::function<void( void * )> cleanup_func_t;
7
8class guard_value_impl {
9public:
10        guard_value_impl() = default;
11
12        ~guard_value_impl() {
13                while( !cleanups.empty() ) {
14                        auto& cleanup = cleanups.top();
15                        cleanup.func( cleanup.val );
16                        cleanups.pop();
17                }
18        }
19
20        void push( cleanup_func_t && func, void* val ) {
21                cleanups.emplace( std::move(func), val );
22        }
23
24private:
25        struct cleanup_t {
26                cleanup_func_t func;
27                void * val;
28
29                cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
30        };
31
32        std::stack< cleanup_t > cleanups;
33};
34
35typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t;
36
37class bool_ref {
38public:
39        bool_ref() = default;
40        ~bool_ref() = default;
41
42        operator bool() { return *m_ref; }
43        bool operator=( bool val ) { return *m_ref = val; }
44
45private:
46
47        template<typename pass>
48        friend class PassVisitor;
49
50        void set( bool & val ) { m_ref = &val; };
51
52        bool * m_ref;
53};
54
55//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
56// Deep magic (a.k.a template meta programming) to make the templated visitor work
57// Basically the goal is to make 2 previsit_impl
58// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
59//     'pass.previsit( node )' that compiles will be used for that node for that type
60//     This requires that this option only compile for passes that actually define an appropriate visit.
61//     SFINAE will make sure the compilation errors in this function don't halt the build.
62//     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
63// 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
64//     This is needed only to eliminate the need for passes to specify any kind of handlers.
65//     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
66//     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
67//     the first implementation takes priority in regards to overloading.
68// Mutator functions work along the same principal
69//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
70// Visit
71template<typename pass_type, typename node_type>
72static inline auto previsit_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.previsit( node ), void() ) {
73        pass.previsit( node );
74}
75
76template<typename pass_type, typename node_type>
77static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
78
79
80template<typename pass_type, typename node_type>
81static inline auto postvisit_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postvisit( node ), void() ) {
82        pass.postvisit( node );
83}
84
85template<typename pass_type, typename node_type>
86static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
87
88// Mutate
89template<typename pass_type, typename node_type>
90static inline auto premutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.premutate( node ), void() ) {
91        return pass.premutate( node );
92}
93
94template<typename pass_type, typename node_type>
95static inline void premutate_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
96
97
98template<typename return_type, typename pass_type, typename node_type>
99static inline auto postmutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postmutate( node ) ) {
100        return pass.postmutate( node );
101}
102
103template<typename return_type, typename pass_type, typename node_type>
104static inline return_type postmutate_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) { return node; }
105
106// Begin/End scope
107template<typename pass_type>
108static inline auto begin_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( pass.beginScope(), void() ) {
109        pass.beginScope();
110}
111
112template<typename pass_type>
113static inline void begin_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
114
115
116template<typename pass_type>
117static inline auto end_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( pass.endScope(), void() ) {
118        pass.endScope();
119}
120
121template<typename pass_type>
122static inline void end_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
123
124// Fields
125#define FIELD_PTR( type, name )                                                                                                        \
126template<typename pass_type>                                                                                                           \
127static inline auto name##_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( &pass.name ) { return &pass.name; } \
128                                                                                                                                       \
129template<typename pass_type>                                                                                                           \
130static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
131
132FIELD_PTR( TypeSubstitution *, env )
133FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
134FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
135FIELD_PTR( std::list< Declaration* >, declsToAddBefore )
136FIELD_PTR( std::list< Declaration* >, declsToAddAfter  )
137FIELD_PTR( bool_ref, visit_children )
138FIELD_PTR( at_cleanup_t, at_cleanup )
139FIELD_PTR( PassVisitor<pass_type> * const, visitor )
Note: See TracBrowser for help on using the repository browser.