source: src/ResolvExpr/SpecCost.cc @ 41606df1

Last change on this file since 41606df1 was 5625427, checked in by Andrew Beach <ajbeach@…>, 9 months ago

Remove the warning directive from SpecCost?, you can't actually use the standard maybe_accept here, it does not allow the user to insert code between visiting elements in a container.

  • Property mode set to 100644
File size: 3.9 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 <type_traits>
19
20#include "AST/Pass.hpp"
21#include "AST/Type.hpp"
22
23namespace ResolvExpr {
24
25namespace {
26
27const ast::Type * expr_result( const ast::ptr< ast::Expr > & expr ) {
28        return expr->result.get();
29}
30
31const ast::Type * type_deref( const ast::ptr< ast::Type > & type ) {
32        return type.get();
33}
34
35        /// The specialization counter inner class.
36        class SpecCounter : public ast::WithShortCircuiting, public ast::WithVisitorRef<SpecCounter> {
37                int count = -1;  ///< specialization count (-1 for none)
38
39                // Converts the max value to -1 (none), otherwise increments the value.
40                static int toNoneOrInc( int value ) {
41                        assert( 0 <= value );
42                        return value < std::numeric_limits<int>::max() ? value + 1 : -1;
43                }
44
45                template<typename T> using MapperT =
46                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
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
54                                if ( ast::Type const * type = mapper( node ) ) {
55                                        ast::Type const * newType = type->accept( *visitor );
56                                        assert( newType == nullptr || newType == type );
57                                }
58
59                                if ( count != -1 && count < minimum ) minimum = count;
60                        }
61                }
62
63                // Returns minimum non-negative count + 1 over type parameters (-1 if none such).
64                template<typename T>
65                int minimumPresent( const T & list, MapperT<T> mapper ) {
66                        int minCount = std::numeric_limits<int>::max();
67                        updateMinimumPresent( minCount, list, mapper );
68                        return toNoneOrInc( minCount );
69                }
70
71        public:
72                int result() const { return 0 <= count ? count : 0; }
73
74                // Mark specialization of base type.
75                void postvisit( const ast::PointerType * ) { if ( count >= 0 ) ++count; }
76                void postvisit( const ast::ArrayType * ) { if ( count >= 0 ) ++count; }
77                void postvisit( const ast::ReferenceType * ) { if ( count >= 0 ) ++count; }
78
79                void postvisit( const ast::StructInstType * ) { if ( count >= 0 ) ++count; }
80                void postvisit( const ast::UnionInstType * ) { if ( count >= 0 ) ++count; }
81
82                // Use the minimal specialization value over returns and params.
83                void previsit( const ast::FunctionType * fty ) {
84                        int minCount = std::numeric_limits<int>::max();
85                        updateMinimumPresent( minCount, fty->params, type_deref );
86                        updateMinimumPresent( minCount, fty->returns, type_deref );
87                        // Add another level to minCount if set.
88                        count = toNoneOrInc( minCount );
89                        // We have already visited children.
90                        visit_children = false;
91                }
92
93                // Look for polymorphic parameters.
94                void previsit( const ast::StructInstType * sty ) {
95                        count = minimumPresent( sty->params, expr_result );
96                }
97
98                // Look for polymorphic parameters.
99                void previsit( const ast::UnionInstType * uty ) {
100                        count = minimumPresent( uty->params, expr_result );
101                }
102
103                // Note polymorphic type (which may be specialized).
104                // xxx - maybe account for open/closed type variables
105                void postvisit( const ast::TypeInstType * ) { count = 0; }
106
107                // Use the minimal specialization over elements.
108                // xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
109                void previsit( const ast::TupleType * tty ) {
110                        count = minimumPresent( tty->types, type_deref );
111                        visit_children = false;
112                }
113        };
114
115} // namespace
116
117int specCost( const ast::Type * type ) {
118        return ( nullptr == type ) ? 0 : ast::Pass<SpecCounter>::read( type );
119}
120
121} // namespace ResolvExpr
122
123// Local Variables: //
124// tab-width: 4 //
125// mode: c++ //
126// compile-command: "make install" //
127// End: //
Note: See TracBrowser for help on using the repository browser.