source: src/SymTab/Autogen.cc@ 72e9222

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 72e9222 was 5f98ce5, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

hoist non-constexpr array dimension into const variable in case of side effects

  • Property mode set to 100644
File size: 27.4 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 : Peter A. Buhr
12// Last Modified On : Tue Jul 12 17:47:17 2016
13// Update Count : 2
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 Type * SizeType = 0;
29
30 class AutogenerateRoutines : public Visitor {
31 public:
32 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
33
34 virtual void visit( EnumDecl *enumDecl );
35 virtual void visit( StructDecl *structDecl );
36 virtual void visit( UnionDecl *structDecl );
37 virtual void visit( TypeDecl *typeDecl );
38 virtual void visit( TraitDecl *ctxDecl );
39 virtual void visit( FunctionDecl *functionDecl );
40
41 virtual void visit( FunctionType *ftype );
42 virtual void visit( PointerType *ftype );
43
44 virtual void visit( CompoundStmt *compoundStmt );
45 virtual void visit( SwitchStmt *switchStmt );
46
47 AutogenerateRoutines() : functionNesting( 0 ) {}
48 private:
49 template< typename StmtClass > void visitStatement( StmtClass *stmt );
50
51 std::list< Declaration * > declsToAdd;
52 std::set< std::string > structsDone;
53 unsigned int functionNesting; // current level of nested functions
54 };
55
56 void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
57 AutogenerateRoutines visitor;
58 acceptAndAdd( translationUnit, visitor, false );
59 }
60
61 bool isUnnamedBitfield( ObjectDecl * obj ) {
62 return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
63 }
64
65 template< typename OutputIterator >
66 void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
67 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
68 copy->get_args().push_back( new VariableExpr( dstParam ) );
69 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
70 copy->get_args().push_back( new SizeofExpr( unionType ) );
71
72 *out++ = new ExprStmt( noLabels, copy );
73 }
74
75 //E ?=?(E volatile*, int),
76 // ?=?(E _Atomic volatile*, int);
77 void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
78 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
79
80 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 );
81 assignType->get_parameters().push_back( dstParam );
82
83 // void ?{}(E *); void ^?{}(E *);
84 FunctionType * ctorType = assignType->clone();
85 FunctionType * dtorType = assignType->clone();
86
87 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
88 assignType->get_parameters().push_back( srcParam );
89 // void ?{}(E *, E);
90 FunctionType *copyCtorType = assignType->clone();
91
92 // T ?=?(E *, E);
93 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
94 assignType->get_returnVals().push_back( returnVal );
95
96 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
97 // right now these cases work, but that might change.
98
99 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
100 // because each unit generates copies of the default routines for each aggregate.
101 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
102 // Really they're something of a cross between instrinsic and autogen, so should
103 // probably make a new linkage type
104 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false );
105 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false );
106 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false );
107 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false );
108 assignDecl->fixUniqueId();
109 ctorDecl->fixUniqueId();
110 copyCtorDecl->fixUniqueId();
111 dtorDecl->fixUniqueId();
112
113 // enum copy construct and assignment is just C-style assignment.
114 // this looks like a bad recursive call, but code gen will turn it into
115 // a C-style assignment.
116 // This happens before function pointer type conversion, so need to do it manually here
117 VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
118 Type *& assignVarExprType = assignVarExpr->get_results().front();
119 assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType );
120 ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr );
121 assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
122 assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
123
124 // body is either return stmt or expr stmt
125 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) );
126 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) );
127
128 declsToAdd.push_back( assignDecl );
129 declsToAdd.push_back( ctorDecl );
130 declsToAdd.push_back( copyCtorDecl );
131 declsToAdd.push_back( dtorDecl );
132 }
133
134 /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
135 template< typename GenericInstType >
136 GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
137 GenericInstType *clone = refType->clone();
138 clone->get_parameters().clear();
139 cloneAll( params, clone->get_parameters() );
140 return clone;
141 }
142
143 /// Creates a new type decl that's the same as src, but renamed and with only the ?=?, ?{} (default and copy), and ^?{} assertions (for complete types only)
144 TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
145 // TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
146
147 // if ( src->get_kind() == TypeDecl::Any ) {
148 // TypeInstType *opParamType = new TypeInstType( Type::Qualifiers(), name, dst );
149 // FunctionType *opFunctionType = new FunctionType( Type::Qualifiers(), false );
150 // opFunctionType->get_parameters().push_back(
151 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), opParamType->clone() ), 0 ) );
152 // FunctionDecl *ctorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
153 // FunctionDecl *dtorAssert = new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
154
155 // opFunctionType->get_parameters().push_back(
156 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType, 0 ) );
157 // FunctionDecl *copyCtorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
158
159 // opFunctionType->get_returnVals().push_back(
160 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType->clone(), 0 ) );
161 // FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType, 0, false, false );
162
163
164 // dst->get_assertions().push_back( assignAssert );
165 // dst->get_assertions().push_back( ctorAssert );
166 // dst->get_assertions().push_back( dtorAssert );
167 // dst->get_assertions().push_back( copyCtorAssert );
168 // }
169
170 TypeDecl *dst = new TypeDecl( src->get_name(), src->get_storageClass(), 0, src->get_kind() );
171 cloneAll(src->get_assertions(), dst->get_assertions());
172 return dst;
173 }
174
175 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric, bool forward = true ) {
176 if ( isGeneric ) {
177 // rewrite member type in terms of the type variables on this operator
178 field = field->clone();
179 genericSubs.apply( field );
180
181 if ( src ) {
182 genericSubs.apply( src );
183 }
184 }
185
186 ObjectDecl * returnVal = NULL;
187 if ( ! func->get_functionType()->get_returnVals().empty() ) {
188 returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
189 }
190
191 // assign to destination (and return value if generic)
192 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
193 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
194 Expression *dstselect = new MemberExpr( field, derefExpr );
195 genImplicitCall( src, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
196
197 if ( isGeneric && returnVal ) {
198 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
199 derefRet->get_args().push_back( new VariableExpr( returnVal ) );
200 Expression *retselect = new MemberExpr( field, derefRet );
201 genImplicitCall( src, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
202 } // if
203 }
204
205 template<typename Iterator>
206 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric, bool forward = true ) {
207 for ( ; member != end; ++member ) {
208 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
209 // query the type qualifiers of this field and skip assigning it if it is marked const.
210 // If it is an array type, we need to strip off the array layers to find its qualifiers.
211 Type * type = field->get_type();
212 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
213 type = at->get_base();
214 }
215
216 if ( type->get_qualifiers().isConst && func->get_name() == "?=?" ) {
217 // don't assign const members, but do construct/destruct
218 continue;
219 }
220
221 if ( field->get_name() == "" ) {
222 // don't assign to anonymous members
223 // xxx - this is a temporary fix. Anonymous members tie into
224 // our inheritance model. I think the correct way to handle this is to
225 // cast the structure to the type of the member and let the resolver
226 // figure out whether it's valid and have a pass afterwards that fixes
227 // the assignment to use pointer arithmetic with the offset of the
228 // member, much like how generic type members are handled.
229 continue;
230 }
231
232 assert( ! func->get_functionType()->get_parameters().empty() );
233 ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
234 ObjectDecl * srcParam = NULL;
235 if ( func->get_functionType()->get_parameters().size() == 2 ) {
236 srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
237 }
238 // srcParam may be NULL, in which case we have default ctor/dtor
239 assert( dstParam );
240
241 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
242 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isGeneric, forward );
243 } // if
244 } // for
245 } // makeStructFunctionBody
246
247 /// generate the body of a constructor which takes parameters that match fields, e.g.
248 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
249 template<typename Iterator>
250 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric ) {
251 FunctionType * ftype = func->get_functionType();
252 std::list<DeclarationWithType*> & params = ftype->get_parameters();
253 assert( params.size() >= 2 ); // should not call this function for default ctor, etc.
254
255 // skip 'this' parameter
256 ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( params.front() );
257 assert( dstParam );
258 std::list<DeclarationWithType*>::iterator parameter = params.begin()+1;
259 for ( ; member != end; ++member ) {
260 if ( DeclarationWithType * field = dynamic_cast<DeclarationWithType*>( *member ) ) {
261 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
262 // don't make a function whose parameter is an unnamed bitfield
263 continue;
264 } else if ( field->get_name() == "" ) {
265 // don't assign to anonymous members
266 // xxx - this is a temporary fix. Anonymous members tie into
267 // our inheritance model. I think the correct way to handle this is to
268 // cast the structure to the type of the member and let the resolver
269 // figure out whether it's valid and have a pass afterwards that fixes
270 // the assignment to use pointer arithmetic with the offset of the
271 // member, much like how generic type members are handled.
272 continue;
273 } else if ( parameter != params.end() ) {
274 // matching parameter, initialize field with copy ctor
275 Expression *srcselect = new VariableExpr(*parameter);
276 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isGeneric );
277 ++parameter;
278 } else {
279 // no matching parameter, initialize field with default ctor
280 makeStructMemberOp( dstParam, NULL, field, func, genericSubs, isGeneric );
281 }
282 }
283 }
284 }
285
286 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
287 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
288
289 // Make function polymorphic in same parameters as generic struct, if applicable
290 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
291 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
292 std::list< Expression* > structParams; // List of matching parameters to put on types
293 TypeSubstitution genericSubs; // Substitutions to make to member types of struct
294 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
295 isGeneric = true;
296 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
297 assignType->get_forall().push_back( typeParam );
298 TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
299 genericSubs.add( (*param)->get_name(), newParamType );
300 structParams.push_back( new TypeExpr( newParamType ) );
301 }
302
303 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
304 assignType->get_parameters().push_back( dstParam );
305
306 // void ?{}(T *); void ^?{}(T *);
307 FunctionType *ctorType = assignType->clone();
308 FunctionType *dtorType = assignType->clone();
309
310 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
311 assignType->get_parameters().push_back( srcParam );
312
313 // void ?{}(T *, T);
314 FunctionType *copyCtorType = assignType->clone();
315
316 // T ?=?(T *, T);
317 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
318 assignType->get_returnVals().push_back( returnVal );
319
320 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
321 // because each unit generates copies of the default routines for each aggregate.
322 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
323 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
324 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
325 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
326 assignDecl->fixUniqueId();
327 ctorDecl->fixUniqueId();
328 copyCtorDecl->fixUniqueId();
329 dtorDecl->fixUniqueId();
330
331 // create constructors which take each member type as a parameter.
332 // for example, for struct A { int x, y; }; generate
333 // void ?{}(A *, int) and void ?{}(A *, int, int)
334 std::list<Declaration *> memCtors;
335 FunctionType * memCtorType = ctorType->clone();
336 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) {
337 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i );
338 assert( member );
339 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) {
340 // don't make a function whose parameter is an unnamed bitfield
341 continue;
342 } else if ( member->get_name() == "" ) {
343 // don't assign to anonymous members
344 // xxx - this is a temporary fix. Anonymous members tie into
345 // our inheritance model. I think the correct way to handle this is to
346 // cast the structure to the type of the member and let the resolver
347 // figure out whether it's valid and have a pass afterwards that fixes
348 // the assignment to use pointer arithmetic with the offset of the
349 // member, much like how generic type members are handled.
350 continue;
351 }
352 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
353 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false );
354 ctor->fixUniqueId();
355 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isGeneric );
356 memCtors.push_back( ctor );
357 }
358 delete memCtorType;
359
360 // generate appropriate calls to member ctor, assignment
361 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isGeneric );
362 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isGeneric );
363 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isGeneric );
364 // needs to do everything in reverse, so pass "forward" as false
365 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isGeneric, false );
366
367 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
368
369 declsToAdd.push_back( assignDecl );
370 declsToAdd.push_back( ctorDecl );
371 declsToAdd.push_back( copyCtorDecl );
372 declsToAdd.push_back( dtorDecl );
373 declsToAdd.splice( declsToAdd.end(), memCtors );
374 }
375
376 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
377 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
378
379 // Make function polymorphic in same parameters as generic union, if applicable
380 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
381 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
382 std::list< Expression* > unionParams; // List of matching parameters to put on types
383 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
384 isGeneric = true;
385 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
386 assignType->get_forall().push_back( typeParam );
387 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
388 }
389
390 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
391 assignType->get_parameters().push_back( dstParam );
392
393 // default ctor/dtor need only first parameter
394 FunctionType * ctorType = assignType->clone();
395 FunctionType * dtorType = assignType->clone();
396
397 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
398 assignType->get_parameters().push_back( srcParam );
399
400 // copy ctor needs both parameters
401 FunctionType * copyCtorType = assignType->clone();
402
403 // assignment needs both and return value
404 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
405 assignType->get_returnVals().push_back( returnVal );
406
407 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
408 // because each unit generates copies of the default routines for each aggregate.
409 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
410 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
411 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false );
412 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
413
414 assignDecl->fixUniqueId();
415 ctorDecl->fixUniqueId();
416 copyCtorDecl->fixUniqueId();
417 dtorDecl->fixUniqueId();
418
419 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
420 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
421
422 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
423
424 // body of assignment and copy ctor is the same
425 copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
426
427 declsToAdd.push_back( assignDecl );
428 declsToAdd.push_back( ctorDecl );
429 declsToAdd.push_back( copyCtorDecl );
430 declsToAdd.push_back( dtorDecl );
431 }
432
433 void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
434 if ( ! enumDecl->get_members().empty() ) {
435 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
436 // enumInst->set_baseEnum( enumDecl );
437 // declsToAdd.push_back(
438 makeEnumFunctions( enumDecl, enumInst, functionNesting, declsToAdd );
439 }
440 }
441
442 void AutogenerateRoutines::visit( StructDecl *structDecl ) {
443 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
444 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
445 structInst.set_baseStruct( structDecl );
446 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
447 structsDone.insert( structDecl->get_name() );
448 } // if
449 }
450
451 void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
452 if ( ! unionDecl->get_members().empty() ) {
453 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
454 unionInst.set_baseUnion( unionDecl );
455 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
456 } // if
457 }
458
459 void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
460 CompoundStmt *stmts = 0;
461 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
462 typeInst->set_baseType( typeDecl );
463 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
464 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
465 if ( typeDecl->get_base() ) {
466 // xxx - generate ctor/dtors for typedecls, e.g.
467 // otype T = int *;
468 stmts = new CompoundStmt( std::list< Label >() );
469 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
470 assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
471 assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
472 stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
473 } // if
474 FunctionType *type = new FunctionType( Type::Qualifiers(), false );
475 type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
476 type->get_parameters().push_back( dst );
477 type->get_parameters().push_back( src );
478 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false );
479 declsToAdd.push_back( func );
480 }
481
482 void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
483 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
484 statements.insert( i, new DeclStmt( noLabels, *decl ) );
485 } // for
486 declsToAdd.clear();
487 }
488
489 void AutogenerateRoutines::visit( FunctionType *) {
490 // ensure that we don't add assignment ops for types defined as part of the function
491 }
492
493 void AutogenerateRoutines::visit( PointerType *) {
494 // ensure that we don't add assignment ops for types defined as part of the pointer
495 }
496
497 void AutogenerateRoutines::visit( TraitDecl *) {
498 // ensure that we don't add assignment ops for types defined as part of the trait
499 }
500
501 template< typename StmtClass >
502 inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
503 std::set< std::string > oldStructs = structsDone;
504 addVisit( stmt, *this );
505 structsDone = oldStructs;
506 }
507
508 void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
509 maybeAccept( functionDecl->get_functionType(), *this );
510 acceptAll( functionDecl->get_oldDecls(), *this );
511 functionNesting += 1;
512 maybeAccept( functionDecl->get_statements(), *this );
513 functionNesting -= 1;
514 }
515
516 void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
517 visitStatement( compoundStmt );
518 }
519
520 void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
521 visitStatement( switchStmt );
522 }
523} // SymTab
Note: See TracBrowser for help on using the repository browser.