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

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new stuck-waitfor-destruct with_gc
Last change on this file since 972e6f7 was 972e6f7, checked in by Rob Schluntz <rschlunt@…>, 10 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.