source: src/GenPoly/InstantiateGeneric.cc @ 5bf4712

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since 5bf4712 was 5bf4712, checked in by Aaron Moss <a3moss@…>, 8 years ago

Generic instantiator now only instantiates complete types; can stub in incomplete types

  • Property mode set to 100644
File size: 11.7 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// InstantiateGeneric.cc --
8//
9// Author           : Aaron B. Moss
10// Created On       : Wed Nov 11 14:55:01 2015
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Wed Nov 11 14:55:01 2015
13// Update Count     : 1
14//
15
16#include <list>
17#include <map>
18#include <string>
19#include <utility>
20#include <vector>
21
22#include "InstantiateGeneric.h"
23#include "DeclMutator.h"
24
25#include "ResolvExpr/typeops.h"
26#include "SymTab/Indexer.h"
27#include "SynTree/Declaration.h"
28#include "SynTree/Mutator.h"
29#include "SynTree/Statement.h"
30#include "SynTree/Type.h"
31#include "SynTree/TypeSubstitution.h"
32
33#include "UniqueName.h"
34#include "utility.h"
35
36namespace GenPoly {
37
38        /// Key for a unique concrete type; generic base type paired with type parameter list
39        struct ConcreteType {
40                ConcreteType() : base(NULL), params() {}
41
42                ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
43
44                ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
45
46                /// Extracts types from a list of TypeExpr*
47                ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
48                        for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
49                                params.push_back( (*param)->get_type()->clone() );
50                        }
51                }
52
53                ConcreteType& operator= (const ConcreteType& that) {
54                        deleteAll( params );
55                        params.clear();
56
57                        base = that.base;
58                        cloneAll( that.params, params );
59
60                        return *this;
61                }
62
63                ~ConcreteType() { deleteAll( params ); }
64
65                bool operator== (const ConcreteType& that) const {
66                        if ( base != that.base ) return false;
67
68                        SymTab::Indexer dummy;
69                        if ( params.size() != that.params.size() ) return false;
70                        for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
71                                if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
72                        }
73                        return true;
74                }
75
76                AggregateDecl *base;        ///< Base generic type
77                std::list< Type* > params;  ///< Instantiation parameters
78        };
79
80        /// Maps a concrete type to the instantiated struct type, accounting for scope
81        class InstantiationMap {
82                /// Instantiation of a generic type, with key information to find it
83                struct Instantiation {
84                        ConcreteType key;     ///< Instantiation parameters for this type
85                        AggregateDecl *decl;  ///< Declaration of the instantiated generic type
86
87                        Instantiation() : key(), decl(0) {}
88                        Instantiation(const ConcreteType &_key, AggregateDecl *_decl) : key(_key), decl(_decl) {}
89                };
90                /// Map of generic types to instantiations of them
91                typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
92
93                std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
94
95        public:
96                /// Starts a new scope
97                void beginScope() {
98                        Scope scope;
99                        scopes.push_back(scope);
100                }
101
102                /// Ends a scope
103                void endScope() {
104                        scopes.pop_back();
105                }
106
107                /// Default constructor initializes with one scope
108                InstantiationMap() { beginScope(); }
109
110        private:
111                /// Gets the declaration for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
112                /// Returns NULL on none such.
113                AggregateDecl* lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
114                        ConcreteType key(generic, params);
115                        // scan scopes from innermost out
116                        for ( std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
117                                // skip scope if no instantiations of this generic type
118                                Scope::const_iterator insts = scope->find( generic );
119                                if ( insts == scope->end() ) continue;
120                                // look through instantiations for matches to concrete type
121                                for ( std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
122                                        if ( inst->key == key ) return inst->decl;
123                                }
124                        }
125                        // no matching instantiation found
126                        return NULL;
127                }
128        public:
129                StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
130                UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
131
132        private:
133                /// Adds a declaration for a concrete type to the current scope
134                void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, AggregateDecl *decl ) {
135                        ConcreteType key(generic, params);
136                        scopes.back()[generic].push_back( Instantiation( key, decl ) );
137                }
138        public:
139                void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
140                void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
141        };
142
143        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
144        class Instantiate : public DeclMutator {
145                InstantiationMap instantiations;
146                UniqueName typeNamer;
147
148        public:
149                Instantiate() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
150
151//              virtual Declaration* mutate( StructDecl *aggregateDecl );
152//              virtual Declaration* mutate( UnionDecl *aggregateDecl );
153
154                virtual Type* mutate( StructInstType *inst );
155                virtual Type* mutate( UnionInstType *inst );
156               
157                virtual void doBeginScope();
158                virtual void doEndScope();
159        };
160       
161        void instantiateGeneric( std::list< Declaration* >& translationUnit ) {
162                Instantiate instantiator;
163                instantiator.mutateDeclarationList( translationUnit );
164        }
165
166        /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
167        bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
168                bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
169
170                // substitute concrete types for given parameters, and incomplete types for placeholders
171                std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
172                std::list< Expression* >::const_iterator param = params.begin();
173                for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
174                        switch ( (*baseParam)->get_kind() ) {
175                        case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
176                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
177                                assert(paramType && "Aggregate parameters should be type expressions");
178                                out.push_back( paramType->clone() );
179                                // check that the substituted type isn't a type variable itself
180                                if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
181                                        allConcrete = false;
182                                }
183                                break;
184                        }
185                        case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
186                                out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
187                                break;
188                        case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
189                                out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
190                                break;
191                        }
192                }
193
194                // if not enough parameters given, substitute remaining incomplete types for placeholders
195                for ( ; baseParam != baseParams.end(); ++baseParam ) {
196                        switch ( (*baseParam)->get_kind() ) {
197                        case TypeDecl::Any:    // no more substitutions here, fail early
198                                return false;
199                        case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
200                                out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
201                                break;
202                        case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
203                                out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
204                                break;
205                        }
206                }
207
208                return allConcrete;
209        }
210       
211        /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
212        void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs, 
213                                                    std::list< Declaration* >& out ) {
214                // substitute types into new members
215                TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
216                for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
217                        Declaration *newMember = (*member)->clone();
218                        subs.apply(newMember);
219                        out.push_back( newMember );
220                }
221        }
222
223        Type* Instantiate::mutate( StructInstType *inst ) {
224                // mutate subtypes
225                Type *mutated = Mutator::mutate( inst );
226                inst = dynamic_cast< StructInstType* >( mutated );
227                if ( ! inst ) return mutated;
228
229                // exit early if no need for further mutation
230                if ( inst->get_parameters().empty() ) return inst;
231                assert( inst->get_baseParameters() && "Base struct has parameters" );
232
233                // check if type can be concretely instantiated; put substitutions into typeSubs
234                std::list< TypeExpr* > typeSubs;
235                if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
236                        deleteAll( typeSubs );
237                        return inst;
238                }
239               
240                // make concrete instantiation of generic type
241                StructDecl *concDecl = instantiations.lookup( inst, typeSubs );
242                if ( ! concDecl ) {
243                        // set concDecl to new type, insert type declaration into statements to add
244                        concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
245                        substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
246                        DeclMutator::addDeclaration( concDecl );
247                        instantiations.insert( inst, typeSubs, concDecl );
248                }
249                StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
250                newInst->set_baseStruct( concDecl );
251
252                deleteAll( typeSubs );
253                delete inst;
254                return newInst;
255        }
256       
257        Type* Instantiate::mutate( UnionInstType *inst ) {
258                // mutate subtypes
259                Type *mutated = Mutator::mutate( inst );
260                inst = dynamic_cast< UnionInstType* >( mutated );
261                if ( ! inst ) return mutated;
262
263                // exit early if no need for further mutation
264                if ( inst->get_parameters().empty() ) return inst;
265                assert( inst->get_baseParameters() && "Base union has parameters" );
266
267                // check if type can be concretely instantiated; put substitutions into typeSubs
268                std::list< TypeExpr* > typeSubs;
269                if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
270                        deleteAll( typeSubs );
271                        return inst;
272                }
273               
274                // make concrete instantiation of generic type
275                UnionDecl *concDecl = instantiations.lookup( inst, typeSubs );
276                if ( ! concDecl ) {
277                        // set concDecl to new type, insert type declaration into statements to add
278                        concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
279                        substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
280                        DeclMutator::addDeclaration( concDecl );
281                        instantiations.insert( inst, typeSubs, concDecl );
282                }
283                UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
284                newInst->set_baseUnion( concDecl );
285
286                deleteAll( typeSubs );
287                delete inst;
288                return newInst;
289        }
290       
291        void Instantiate::doBeginScope() {
292                DeclMutator::doBeginScope();
293                // push a new concrete type scope
294                instantiations.beginScope();
295        }
296
297        void Instantiate::doEndScope() {
298                DeclMutator::doEndScope();
299                // pop the last concrete type scope
300                instantiations.endScope();
301        }
302       
303}  // namespace GenPoly
304
305// Local Variables: //
306// tab-width: 4 //
307// mode: c++ //
308// compile-command: "make install" //
309// End: //
Note: See TracBrowser for help on using the repository browser.