source: src/ResolvExpr/SpecCost.cc @ 27316b4

Last change on this file since 27316b4 was c6b4432, checked in by Andrew Beach <ajbeach@…>, 8 months ago

Remove BaseSyntaxNode? and clean-up.

  • Property mode set to 100644
File size: 4.2 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// SpecCost.cc --
8//
9// Author           : Aaron B. Moss
10// Created On       : Tue Oct 02 15:50:00 2018
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Jul  3 11:07:00 2019
13// Update Count     : 3
14//
15
16#include <cassert>
17#include <limits>
18#include <list>
19#include <type_traits>
20
21#include "AST/Pass.hpp"
22#include "AST/Type.hpp"
23
24namespace ResolvExpr {
25
26namespace {
27        /// The specialization counter inner class.
28        class SpecCounter : public ast::WithShortCircuiting, public ast::WithVisitorRef<SpecCounter> {
29                int count = -1;  ///< specialization count (-1 for none)
30
31                // Converts the max value to -1 (none), otherwise increments the value.
32                static int toNoneOrInc( int value ) {
33                        assert( 0 <= value );
34                        return value < std::numeric_limits<int>::max() ? value + 1 : -1;
35                }
36
37                template<typename T> using MapperT =
38                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
39
40                #warning Should use a standard maybe_accept
41                void maybe_accept( ast::Type const * type ) {
42                        if ( type ) {
43                                auto node = type->accept( *visitor );
44                                assert( node == nullptr || node == type );
45                        }
46                }
47
48                // Update the minimum to the new lowest non-none value.
49                template<typename T>
50                void updateMinimumPresent( int & minimum, const T & list, MapperT<T> mapper ) {
51                        for ( const auto & node : list ) {
52                                count = -1;
53                                maybe_accept( mapper( node ) );
54                                if ( count != -1 && count < minimum ) minimum = count;
55                        }
56                }
57
58                // Returns minimum non-negative count + 1 over type parameters (-1 if none such).
59                template<typename T>
60                int minimumPresent( const T & list, MapperT<T> mapper ) {
61                        int minCount = std::numeric_limits<int>::max();
62                        updateMinimumPresent( minCount, list, mapper );
63                        return toNoneOrInc( minCount );
64                }
65
66                // The three mappers:
67                static const ast::Type * decl_type( const ast::ptr< ast::DeclWithType > & decl ) {
68                        return decl->get_type();
69                }
70                static const ast::Type * expr_result( const ast::ptr< ast::Expr > & expr ) {
71                        return expr->result;
72                }
73                static const ast::Type * type_deref( const ast::ptr< ast::Type > & type ) {
74                        return type.get();
75                }
76
77        public:
78                int get_count() const { return 0 <= count ? count : 0; }
79
80                // Mark specialization of base type.
81                void postvisit( const ast::PointerType * ) { if ( count >= 0 ) ++count; }
82                void postvisit( const ast::ArrayType * ) { if ( count >= 0 ) ++count; }
83                void postvisit( const ast::ReferenceType * ) { if ( count >= 0 ) ++count; }
84
85                void postvisit( const ast::StructInstType * ) { if ( count >= 0 ) ++count; }
86                void postvisit( const ast::UnionInstType * ) { if ( count >= 0 ) ++count; }
87
88                // Use the minimal specialization value over returns and params.
89                void previsit( const ast::FunctionType * fty ) {
90                        int minCount = std::numeric_limits<int>::max();
91                        updateMinimumPresent( minCount, fty->params, type_deref );
92                        updateMinimumPresent( minCount, fty->returns, type_deref );
93                        // Add another level to minCount if set.
94                        count = toNoneOrInc( minCount );
95                        // We have already visited children.
96                        visit_children = false;
97                }
98
99                // Look for polymorphic parameters.
100                void previsit( const ast::StructInstType * sty ) {
101                        count = minimumPresent( sty->params, expr_result );
102                }
103
104                // Look for polymorphic parameters.
105                void previsit( const ast::UnionInstType * uty ) {
106                        count = minimumPresent( uty->params, expr_result );
107                }
108
109                // Note polymorphic type (which may be specialized).
110                // xxx - maybe account for open/closed type variables
111                void postvisit( const ast::TypeInstType * ) { count = 0; }
112
113                // Use the minimal specialization over elements.
114                // xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
115                void previsit( const ast::TupleType * tty ) {
116                        count = minimumPresent( tty->types, type_deref );
117                        visit_children = false;
118                }
119        };
120
121} // namespace
122
123int specCost( const ast::Type * type ) {
124        if ( nullptr == type ) {
125                return 0;
126        }
127        ast::Pass<SpecCounter> counter;
128        type->accept( counter );
129        return counter.core.get_count();
130}
131
132} // namespace ResolvExpr
133
134// Local Variables: //
135// tab-width: 4 //
136// mode: c++ //
137// compile-command: "make install" //
138// End: //
Note: See TracBrowser for help on using the repository browser.