source: src/SymTab/Autogen.cc @ 5b40f30

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

generate correct empty list initializer, ensure function return value is not incorrectly destructed before it is returned, do not add src parameter to autogenerated routines when they take a single argument

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