source: src/SymTab/Autogen.cc @ 972e6f7

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglergc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 972e6f7 was 972e6f7, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

separate autogen into Autogen.{cc,h}, make array destruction generate properly, generalize autogeneration routines

  • Property mode set to 100644
File size: 23.3 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// Autogen.cc --
8//
9// Author           : Rob Schluntz
10// Created On       : Thu Mar 03 15:45:56 2016
11// Last Modified By : Rob Schluntz
12// Last Modified On : Thu Mar 03 15:45:56 2016
13// Update Count     : 1
14//
15
16#include <list>
17#include <iterator>
18#include "SynTree/Visitor.h"
19#include "SynTree/Type.h"
20#include "SynTree/Statement.h"
21#include "SynTree/TypeSubstitution.h"
22#include "Common/utility.h"
23#include "AddVisit.h"
24#include "MakeLibCfa.h"
25#include "Autogen.h"
26
27namespace SymTab {
28        class AutogenerateRoutines : public Visitor {
29                public:
30                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
31
32                virtual void visit( EnumDecl *enumDecl );
33                virtual void visit( StructDecl *structDecl );
34                virtual void visit( UnionDecl *structDecl );
35                virtual void visit( TypeDecl *typeDecl );
36                virtual void visit( ContextDecl *ctxDecl );
37                virtual void visit( FunctionDecl *functionDecl );
38
39                virtual void visit( FunctionType *ftype );
40                virtual void visit( PointerType *ftype );
41
42                virtual void visit( CompoundStmt *compoundStmt );
43                virtual void visit( IfStmt *ifStmt );
44                virtual void visit( WhileStmt *whileStmt );
45                virtual void visit( ForStmt *forStmt );
46                virtual void visit( SwitchStmt *switchStmt );
47                virtual void visit( ChooseStmt *chooseStmt );
48                virtual void visit( CaseStmt *caseStmt );
49                virtual void visit( CatchStmt *catchStmt );
50
51                AutogenerateRoutines() : functionNesting( 0 ) {}
52                private:
53                template< typename StmtClass > void visitStatement( StmtClass *stmt );
54
55                std::list< Declaration * > declsToAdd;
56                std::set< std::string > structsDone;
57                unsigned int functionNesting;     // current level of nested functions
58        };
59
60        void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
61                AutogenerateRoutines visitor;
62                acceptAndAdd( translationUnit, visitor, false );
63        }
64
65        template< typename OutputIterator >
66        void makeScalarFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
67                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
68                // unnamed bit fields are not copied as they cannot be accessed
69                if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
70
71                // want to be able to generate assignment, ctor, and dtor generically,
72                // so fname is either ?=?, ?{}, or ^?{}
73                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
74
75                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
76                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
77
78                // do something special for unnamed members
79                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
80                fExpr->get_args().push_back( dstselect );
81
82                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
83                fExpr->get_args().push_back( srcselect );
84
85                *out++ = new ExprStmt( noLabels, fExpr );
86        }
87
88        template< typename OutputIterator >
89        void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
90                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
91                copy->get_args().push_back( new VariableExpr( dstParam ) );
92                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
93                copy->get_args().push_back( new SizeofExpr( unionType ) );
94
95                *out++ = new ExprStmt( noLabels, copy );
96        }
97
98        //E ?=?(E volatile*, int),
99        //  ?=?(E _Atomic volatile*, int);
100        void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
101                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
102
103                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
104                assignType->get_returnVals().push_back( returnVal );
105
106                // need two assignment operators with different types
107                FunctionType * assignType2 = assignType->clone();
108
109                // E ?=?(E volatile *, E)
110                Type *etype = refType->clone();
111                // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
112
113                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
114                assignType->get_parameters().push_back( dstParam );
115
116                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
117                assignType->get_parameters().push_back( srcParam );
118
119                // E ?=?(E volatile *, int)
120                assignType2->get_parameters().push_back( dstParam->clone() );
121                BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
122                ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
123                assignType2->get_parameters().push_back( srcParam2 );
124
125                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
126                // because each unit generates copies of the default routines for each aggregate.
127
128                // since there is no definition, these should not be inline
129                // make these intrinsic so that the code generator does not make use of them
130                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
131                assignDecl->fixUniqueId();
132                FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
133                assignDecl2->fixUniqueId();
134
135                // these should be built in the same way that the prelude
136                // functions are, so build a list containing the prototypes
137                // and allow MakeLibCfa to autogenerate the bodies.
138                std::list< Declaration * > assigns;
139                assigns.push_back( assignDecl );
140                assigns.push_back( assignDecl2 );
141
142                LibCfa::makeLibCfa( assigns );
143
144                // need to remove the prototypes, since this may be nested in a routine
145                for (int start = 0, end = assigns.size()/2; start < end; start++) {
146                        delete assigns.front();
147                        assigns.pop_front();
148                } // for
149
150                declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
151        }
152
153        /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
154        template< typename GenericInstType >
155        GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
156                GenericInstType *clone = refType->clone();
157                clone->get_parameters().clear();
158                cloneAll( params, clone->get_parameters() );
159                return clone;
160        }
161
162        /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
163        TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
164                TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
165
166                if ( src->get_kind() == TypeDecl::Any ) {
167                        // just include assignment operator assertion
168                        TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
169                        FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
170                        assignFunctionType->get_returnVals().push_back(
171                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
172                        assignFunctionType->get_parameters().push_back(
173                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
174                        assignFunctionType->get_parameters().push_back(
175                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
176                        FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
177                        dst->get_assertions().push_back( assignAssert );
178                }
179
180                return dst;
181        }
182
183        template<typename Iterator>
184        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric, bool forward = true ) {
185                for ( ; member != end; ++member ) {
186                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
187                                // query the type qualifiers of this field and skip assigning it if it is marked const.
188                                // If it is an array type, we need to strip off the array layers to find its qualifiers.
189                                Type * type = dwt->get_type();
190                                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
191                                        type = at->get_base();
192                                }
193
194                                if ( type->get_qualifiers().isConst ) {
195                                        // don't assign const members
196                                        continue;
197                                }
198
199                                assert( ! func->get_functionType()->get_parameters().empty() );
200                                ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
201                                ObjectDecl * srcParam = NULL;
202                                if ( func->get_functionType()->get_parameters().size() == 2 ) {
203                                        srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
204                                }
205                                ObjectDecl * returnVal = NULL;
206                                if ( ! func->get_functionType()->get_returnVals().empty() ) {
207                                        returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
208                                }
209                                // srcParam may be NULL, in which case we have default ctor/dtor
210                                assert( dstParam );
211
212
213                                DeclarationWithType * memType = dwt;
214                                if ( isGeneric ) {
215                                        // rewrite member type in terms of the type variables on this operator
216                                        memType = memType->clone();
217                                        genericSubs.apply( memType );
218                                }
219
220
221                                // assign to destination (and return value if generic)
222                                if ( ArrayType *array = dynamic_cast< ArrayType * >( memType->get_type() ) ) {
223                                        UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
224                                        derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
225                                        Expression *dstselect = new MemberExpr( memType, derefExpr );
226                                        Expression *srcselect = srcParam ? new MemberExpr( memType, new VariableExpr( srcParam ) ) : NULL;
227
228                                        makeArrayFunction( srcselect, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
229                                        if ( isGeneric && returnVal ) {
230                                                UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
231                                                derefRet->get_args().push_back( new VariableExpr( returnVal ) );
232                                                Expression *retselect = new MemberExpr( memType, derefRet );
233
234                                                makeArrayFunction( srcselect, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
235                                        }
236                                } else {
237                                        makeScalarFunction( srcParam, dstParam, memType, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
238                                        if ( isGeneric && returnVal ) makeScalarFunction( srcParam, returnVal, memType, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
239                                } // if
240                        } // if
241                } // for
242        } // makeStructFunctionBody
243
244        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
245                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
246
247                // Make function polymorphic in same parameters as generic struct, if applicable
248                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
249                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
250                std::list< Expression* > structParams;  // List of matching parameters to put on types
251                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
252                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
253                        isGeneric = true;
254                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
255                        assignType->get_forall().push_back( typeParam );
256                        TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
257                        genericSubs.add( (*param)->get_name(), newParamType );
258                        structParams.push_back( new TypeExpr( newParamType ) );
259                }
260
261                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
262                assignType->get_parameters().push_back( dstParam );
263
264                // void ?{}(T *); void ^?{}(T *);
265                FunctionType *ctorType = assignType->clone();
266                FunctionType *dtorType = assignType->clone();
267
268                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
269                assignType->get_parameters().push_back( srcParam );
270
271                // void ?{}(T *, T);
272                FunctionType *copyCtorType = assignType->clone();
273
274                // T ?=?(T *, T);
275                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
276                assignType->get_returnVals().push_back( returnVal );
277
278                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
279                // because each unit generates copies of the default routines for each aggregate.
280                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
281                FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
282                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
283                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
284                assignDecl->fixUniqueId();
285                ctorDecl->fixUniqueId();
286                copyCtorDecl->fixUniqueId();
287                dtorDecl->fixUniqueId();
288
289                // generate appropriate calls to member ctor, assignment
290                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isGeneric );
291                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isGeneric );
292                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isGeneric );
293                // needs to do everything in reverse, so pass "forward" as false
294                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isGeneric, false );
295
296                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
297
298                declsToAdd.push_back( assignDecl );
299                declsToAdd.push_back( ctorDecl );
300                declsToAdd.push_back( copyCtorDecl );
301                declsToAdd.push_back( dtorDecl );
302        }
303
304        void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
305                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
306
307                // Make function polymorphic in same parameters as generic union, if applicable
308                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
309                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
310                std::list< Expression* > unionParams;  // List of matching parameters to put on types
311                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
312                        isGeneric = true;
313                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
314                        assignType->get_forall().push_back( typeParam );
315                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
316                }
317
318                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
319                assignType->get_parameters().push_back( dstParam );
320
321                // default ctor/dtor need only first parameter
322                FunctionType * ctorType = assignType->clone();
323                FunctionType * dtorType = assignType->clone();
324
325                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
326                assignType->get_parameters().push_back( srcParam );
327
328                // copy ctor needs both parameters
329                FunctionType * copyCtorType = assignType->clone();
330
331                // assignment needs both and return value
332                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
333                assignType->get_returnVals().push_back( returnVal );
334
335                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
336                // because each unit generates copies of the default routines for each aggregate.
337                FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
338                FunctionDecl *ctorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
339                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false );
340                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
341
342                assignDecl->fixUniqueId();
343                ctorDecl->fixUniqueId();
344                copyCtorDecl->fixUniqueId();
345                dtorDecl->fixUniqueId();
346
347                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
348                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
349
350                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
351
352                // body of assignment and copy ctor is the same
353                copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
354
355                declsToAdd.push_back( assignDecl );
356                declsToAdd.push_back( ctorDecl );
357                declsToAdd.push_back( copyCtorDecl );
358                declsToAdd.push_back( dtorDecl );
359        }
360
361        void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
362                if ( ! enumDecl->get_members().empty() ) {
363                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
364                        // enumInst->set_baseEnum( enumDecl );
365                        // declsToAdd.push_back(
366                        makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
367                }
368        }
369
370        void AutogenerateRoutines::visit( StructDecl *structDecl ) {
371                if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
372                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
373                        structInst.set_baseStruct( structDecl );
374                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
375                        structsDone.insert( structDecl->get_name() );
376                } // if
377        }
378
379        void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
380                if ( ! unionDecl->get_members().empty() ) {
381                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
382                        unionInst.set_baseUnion( unionDecl );
383                        makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
384                } // if
385        }
386
387        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
388                CompoundStmt *stmts = 0;
389                TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
390                typeInst->set_baseType( typeDecl );
391                ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
392                ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
393                if ( typeDecl->get_base() ) {
394                        stmts = new CompoundStmt( std::list< Label >() );
395                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
396                        assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
397                        assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
398                        stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
399                } // if
400                FunctionType *type = new FunctionType( Type::Qualifiers(), false );
401                type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
402                type->get_parameters().push_back( dst );
403                type->get_parameters().push_back( src );
404                FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
405                declsToAdd.push_back( func );
406        }
407
408        void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
409                for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
410                        statements.insert( i, new DeclStmt( noLabels, *decl ) );
411                } // for
412                declsToAdd.clear();
413        }
414
415        void AutogenerateRoutines::visit( FunctionType *) {
416                // ensure that we don't add assignment ops for types defined as part of the function
417        }
418
419        void AutogenerateRoutines::visit( PointerType *) {
420                // ensure that we don't add assignment ops for types defined as part of the pointer
421        }
422
423        void AutogenerateRoutines::visit( ContextDecl *) {
424                // ensure that we don't add assignment ops for types defined as part of the context
425        }
426
427        template< typename StmtClass >
428        inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
429                std::set< std::string > oldStructs = structsDone;
430                addVisit( stmt, *this );
431                structsDone = oldStructs;
432        }
433
434        void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
435                maybeAccept( functionDecl->get_functionType(), *this );
436                acceptAll( functionDecl->get_oldDecls(), *this );
437                functionNesting += 1;
438                maybeAccept( functionDecl->get_statements(), *this );
439                functionNesting -= 1;
440        }
441
442        void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
443                visitStatement( compoundStmt );
444        }
445
446        void AutogenerateRoutines::visit( IfStmt *ifStmt ) {
447                visitStatement( ifStmt );
448        }
449
450        void AutogenerateRoutines::visit( WhileStmt *whileStmt ) {
451                visitStatement( whileStmt );
452        }
453
454        void AutogenerateRoutines::visit( ForStmt *forStmt ) {
455                visitStatement( forStmt );
456        }
457
458        void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
459                visitStatement( switchStmt );
460        }
461
462        void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
463                visitStatement( switchStmt );
464        }
465
466        void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
467                visitStatement( caseStmt );
468        }
469
470        void AutogenerateRoutines::visit( CatchStmt *cathStmt ) {
471                visitStatement( cathStmt );
472        }
473
474} // SymTab
Note: See TracBrowser for help on using the repository browser.