source: src/SymTab/Validate.cc@ 71bd8c6

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 string with_gc
Last change on this file since 71bd8c6 was cc79d97, checked in by Rob Schluntz <rschlunt@…>, 10 years ago

incorrectly redefining a typedef will cause an error in most cases

  • Property mode set to 100644
File size: 34.5 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// Validate.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 21:50:04 2015
11// Last Modified By : Rob Schluntz
12// Last Modified On : Wed Jul 08 12:49:36 2015
13// Update Count : 166
14//
15
16// The "validate" phase of translation is used to take a syntax tree and convert it into a standard form that aims to be
17// as regular in structure as possible. Some assumptions can be made regarding the state of the tree after this pass is
18// complete, including:
19//
20// - No nested structure or union definitions; any in the input are "hoisted" to the level of the containing struct or
21// union.
22//
23// - All enumeration constants have type EnumInstType.
24//
25// - The type "void" never occurs in lists of function parameter or return types; neither do tuple types. A function
26// taking no arguments has no argument types, and tuples are flattened.
27//
28// - No context instances exist; they are all replaced by the set of declarations signified by the context, instantiated
29// by the particular set of type arguments.
30//
31// - Every declaration is assigned a unique id.
32//
33// - No typedef declarations or instances exist; the actual type is substituted for each instance.
34//
35// - Each type, struct, and union definition is followed by an appropriate assignment operator.
36//
37// - Each use of a struct or union is connected to a complete definition of that struct or union, even if that
38// definition occurs later in the input.
39
40#include <list>
41#include <iterator>
42#include "Validate.h"
43#include "SynTree/Visitor.h"
44#include "SynTree/Mutator.h"
45#include "SynTree/Type.h"
46#include "SynTree/Statement.h"
47#include "SynTree/TypeSubstitution.h"
48#include "Indexer.h"
49#include "FixFunction.h"
50// #include "ImplementationType.h"
51#include "utility.h"
52#include "UniqueName.h"
53#include "AddVisit.h"
54#include "MakeLibCfa.h"
55#include "TypeEquality.h"
56
57#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
58
59namespace SymTab {
60 class HoistStruct : public Visitor {
61 public:
62 static void hoistStruct( std::list< Declaration * > &translationUnit );
63
64 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
65
66 virtual void visit( StructDecl *aggregateDecl );
67 virtual void visit( UnionDecl *aggregateDecl );
68
69 virtual void visit( CompoundStmt *compoundStmt );
70 virtual void visit( IfStmt *ifStmt );
71 virtual void visit( WhileStmt *whileStmt );
72 virtual void visit( ForStmt *forStmt );
73 virtual void visit( SwitchStmt *switchStmt );
74 virtual void visit( ChooseStmt *chooseStmt );
75 virtual void visit( CaseStmt *caseStmt );
76 virtual void visit( CatchStmt *catchStmt );
77 private:
78 HoistStruct();
79
80 template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
81
82 std::list< Declaration * > declsToAdd;
83 bool inStruct;
84 };
85
86 class Pass1 : public Visitor {
87 typedef Visitor Parent;
88 virtual void visit( EnumDecl *aggregateDecl );
89 virtual void visit( FunctionType *func );
90 };
91
92 class Pass2 : public Indexer {
93 typedef Indexer Parent;
94 public:
95 Pass2( bool doDebug, const Indexer *indexer );
96 private:
97 virtual void visit( StructInstType *structInst );
98 virtual void visit( UnionInstType *unionInst );
99 virtual void visit( ContextInstType *contextInst );
100 virtual void visit( StructDecl *structDecl );
101 virtual void visit( UnionDecl *unionDecl );
102 virtual void visit( TypeInstType *typeInst );
103
104 const Indexer *indexer;
105
106 typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
107 typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
108 ForwardStructsType forwardStructs;
109 ForwardUnionsType forwardUnions;
110 };
111
112 class Pass3 : public Indexer {
113 typedef Indexer Parent;
114 public:
115 Pass3( const Indexer *indexer );
116 private:
117 virtual void visit( ObjectDecl *object );
118 virtual void visit( FunctionDecl *func );
119
120 const Indexer *indexer;
121 };
122
123 class AddStructAssignment : public Visitor {
124 public:
125 static void addStructAssignment( std::list< Declaration * > &translationUnit );
126
127 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
128
129 virtual void visit( EnumDecl *enumDecl );
130 virtual void visit( StructDecl *structDecl );
131 virtual void visit( UnionDecl *structDecl );
132 virtual void visit( TypeDecl *typeDecl );
133 virtual void visit( ContextDecl *ctxDecl );
134 virtual void visit( FunctionDecl *functionDecl );
135
136 virtual void visit( FunctionType *ftype );
137 virtual void visit( PointerType *ftype );
138
139 virtual void visit( CompoundStmt *compoundStmt );
140 virtual void visit( IfStmt *ifStmt );
141 virtual void visit( WhileStmt *whileStmt );
142 virtual void visit( ForStmt *forStmt );
143 virtual void visit( SwitchStmt *switchStmt );
144 virtual void visit( ChooseStmt *chooseStmt );
145 virtual void visit( CaseStmt *caseStmt );
146 virtual void visit( CatchStmt *catchStmt );
147
148 AddStructAssignment() : functionNesting( 0 ) {}
149 private:
150 template< typename StmtClass > void visitStatement( StmtClass *stmt );
151
152 std::list< Declaration * > declsToAdd;
153 std::set< std::string > structsDone;
154 unsigned int functionNesting; // current level of nested functions
155 };
156
157 class EliminateTypedef : public Mutator {
158 public:
159 EliminateTypedef() : scopeLevel( 0 ) {}
160 static void eliminateTypedef( std::list< Declaration * > &translationUnit );
161 private:
162 virtual Declaration *mutate( TypedefDecl *typeDecl );
163 virtual TypeDecl *mutate( TypeDecl *typeDecl );
164 virtual DeclarationWithType *mutate( FunctionDecl *funcDecl );
165 virtual ObjectDecl *mutate( ObjectDecl *objDecl );
166 virtual CompoundStmt *mutate( CompoundStmt *compoundStmt );
167 virtual Type *mutate( TypeInstType *aggregateUseType );
168 virtual Expression *mutate( CastExpr *castExpr );
169
170 typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap;
171 TypedefMap typedefNames;
172 int scopeLevel;
173 };
174
175 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
176 Pass1 pass1;
177 Pass2 pass2( doDebug, 0 );
178 Pass3 pass3( 0 );
179 EliminateTypedef::eliminateTypedef( translationUnit );
180 HoistStruct::hoistStruct( translationUnit );
181 acceptAll( translationUnit, pass1 );
182 acceptAll( translationUnit, pass2 );
183 // need to collect all of the assignment operators prior to
184 // this point and only generate assignment operators if one doesn't exist
185 AddStructAssignment::addStructAssignment( translationUnit );
186 acceptAll( translationUnit, pass3 );
187 }
188
189 void validateType( Type *type, const Indexer *indexer ) {
190 Pass1 pass1;
191 Pass2 pass2( false, indexer );
192 Pass3 pass3( indexer );
193 type->accept( pass1 );
194 type->accept( pass2 );
195 type->accept( pass3 );
196 }
197
198 template< typename Visitor >
199 void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
200 std::list< Declaration * >::iterator i = translationUnit.begin();
201 while ( i != translationUnit.end() ) {
202 (*i)->accept( visitor );
203 std::list< Declaration * >::iterator next = i;
204 next++;
205 if ( ! visitor.get_declsToAdd().empty() ) {
206 translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
207 } // if
208 i = next;
209 } // while
210 }
211
212 void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
213 HoistStruct hoister;
214 acceptAndAdd( translationUnit, hoister, true );
215 }
216
217 HoistStruct::HoistStruct() : inStruct( false ) {
218 }
219
220 void filter( std::list< Declaration * > &declList, bool (*pred)( Declaration * ), bool doDelete ) {
221 std::list< Declaration * >::iterator i = declList.begin();
222 while ( i != declList.end() ) {
223 std::list< Declaration * >::iterator next = i;
224 ++next;
225 if ( pred( *i ) ) {
226 if ( doDelete ) {
227 delete *i;
228 } // if
229 declList.erase( i );
230 } // if
231 i = next;
232 } // while
233 }
234
235 bool isStructOrUnion( Declaration *decl ) {
236 return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
237 }
238
239 template< typename AggDecl >
240 void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
241 if ( inStruct ) {
242 // Add elements in stack order corresponding to nesting structure.
243 declsToAdd.push_front( aggregateDecl );
244 Visitor::visit( aggregateDecl );
245 } else {
246 inStruct = true;
247 Visitor::visit( aggregateDecl );
248 inStruct = false;
249 } // if
250 // Always remove the hoisted aggregate from the inner structure.
251 filter( aggregateDecl->get_members(), isStructOrUnion, false );
252 }
253
254 void HoistStruct::visit( StructDecl *aggregateDecl ) {
255 handleAggregate( aggregateDecl );
256 }
257
258 void HoistStruct::visit( UnionDecl *aggregateDecl ) {
259 handleAggregate( aggregateDecl );
260 }
261
262 void HoistStruct::visit( CompoundStmt *compoundStmt ) {
263 addVisit( compoundStmt, *this );
264 }
265
266 void HoistStruct::visit( IfStmt *ifStmt ) {
267 addVisit( ifStmt, *this );
268 }
269
270 void HoistStruct::visit( WhileStmt *whileStmt ) {
271 addVisit( whileStmt, *this );
272 }
273
274 void HoistStruct::visit( ForStmt *forStmt ) {
275 addVisit( forStmt, *this );
276 }
277
278 void HoistStruct::visit( SwitchStmt *switchStmt ) {
279 addVisit( switchStmt, *this );
280 }
281
282 void HoistStruct::visit( ChooseStmt *switchStmt ) {
283 addVisit( switchStmt, *this );
284 }
285
286 void HoistStruct::visit( CaseStmt *caseStmt ) {
287 addVisit( caseStmt, *this );
288 }
289
290 void HoistStruct::visit( CatchStmt *cathStmt ) {
291 addVisit( cathStmt, *this );
292 }
293
294 void Pass1::visit( EnumDecl *enumDecl ) {
295 // Set the type of each member of the enumeration to be EnumConstant
296
297 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
298 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
299 assert( obj );
300 // obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
301 BasicType * enumType = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
302 obj->set_type( enumType ) ;
303 } // for
304 Parent::visit( enumDecl );
305 }
306
307 namespace {
308 template< typename DWTIterator >
309 void fixFunctionList( DWTIterator begin, DWTIterator end, FunctionType *func ) {
310 // the only case in which "void" is valid is where it is the only one in the list; then it should be removed
311 // entirely other fix ups are handled by the FixFunction class
312 if ( begin == end ) return;
313 FixFunction fixer;
314 DWTIterator i = begin;
315 *i = (*i )->acceptMutator( fixer );
316 if ( fixer.get_isVoid() ) {
317 DWTIterator j = i;
318 ++i;
319 func->get_parameters().erase( j );
320 if ( i != end ) {
321 throw SemanticError( "invalid type void in function type ", func );
322 } // if
323 } else {
324 ++i;
325 for ( ; i != end; ++i ) {
326 FixFunction fixer;
327 *i = (*i )->acceptMutator( fixer );
328 if ( fixer.get_isVoid() ) {
329 throw SemanticError( "invalid type void in function type ", func );
330 } // if
331 } // for
332 } // if
333 }
334 }
335
336 void Pass1::visit( FunctionType *func ) {
337 // Fix up parameters and return types
338 fixFunctionList( func->get_parameters().begin(), func->get_parameters().end(), func );
339 fixFunctionList( func->get_returnVals().begin(), func->get_returnVals().end(), func );
340 Visitor::visit( func );
341 }
342
343 Pass2::Pass2( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
344 if ( other_indexer ) {
345 indexer = other_indexer;
346 } else {
347 indexer = this;
348 } // if
349 }
350
351 void Pass2::visit( StructInstType *structInst ) {
352 Parent::visit( structInst );
353 StructDecl *st = indexer->lookupStruct( structInst->get_name() );
354 // it's not a semantic error if the struct is not found, just an implicit forward declaration
355 if ( st ) {
356 assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
357 structInst->set_baseStruct( st );
358 } // if
359 if ( ! st || st->get_members().empty() ) {
360 // use of forward declaration
361 forwardStructs[ structInst->get_name() ].push_back( structInst );
362 } // if
363 }
364
365 void Pass2::visit( UnionInstType *unionInst ) {
366 Parent::visit( unionInst );
367 UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
368 // it's not a semantic error if the union is not found, just an implicit forward declaration
369 if ( un ) {
370 unionInst->set_baseUnion( un );
371 } // if
372 if ( ! un || un->get_members().empty() ) {
373 // use of forward declaration
374 forwardUnions[ unionInst->get_name() ].push_back( unionInst );
375 } // if
376 }
377
378 void Pass2::visit( ContextInstType *contextInst ) {
379 Parent::visit( contextInst );
380 ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() );
381 if ( ! ctx ) {
382 throw SemanticError( "use of undeclared context " + contextInst->get_name() );
383 } // if
384 for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) {
385 for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
386 if ( ContextInstType *otherCtx = dynamic_cast< ContextInstType * >(*assert ) ) {
387 cloneAll( otherCtx->get_members(), contextInst->get_members() );
388 } else {
389 contextInst->get_members().push_back( (*assert )->clone() );
390 } // if
391 } // for
392 } // for
393 applySubstitution( ctx->get_parameters().begin(), ctx->get_parameters().end(), contextInst->get_parameters().begin(), ctx->get_members().begin(), ctx->get_members().end(), back_inserter( contextInst->get_members() ) );
394 }
395
396 void Pass2::visit( StructDecl *structDecl ) {
397 if ( ! structDecl->get_members().empty() ) {
398 ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
399 if ( fwds != forwardStructs.end() ) {
400 for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
401 (*inst )->set_baseStruct( structDecl );
402 } // for
403 forwardStructs.erase( fwds );
404 } // if
405 } // if
406 Indexer::visit( structDecl );
407 }
408
409 void Pass2::visit( UnionDecl *unionDecl ) {
410 if ( ! unionDecl->get_members().empty() ) {
411 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
412 if ( fwds != forwardUnions.end() ) {
413 for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
414 (*inst )->set_baseUnion( unionDecl );
415 } // for
416 forwardUnions.erase( fwds );
417 } // if
418 } // if
419 Indexer::visit( unionDecl );
420 }
421
422 void Pass2::visit( TypeInstType *typeInst ) {
423 if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
424 if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
425 typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
426 } // if
427 } // if
428 }
429
430 Pass3::Pass3( const Indexer *other_indexer ) : Indexer( false ) {
431 if ( other_indexer ) {
432 indexer = other_indexer;
433 } else {
434 indexer = this;
435 } // if
436 }
437
438 void forallFixer( Type *func ) {
439 // Fix up assertions
440 for ( std::list< TypeDecl * >::iterator type = func->get_forall().begin(); type != func->get_forall().end(); ++type ) {
441 std::list< DeclarationWithType * > toBeDone, nextRound;
442 toBeDone.splice( toBeDone.end(), (*type )->get_assertions() );
443 while ( ! toBeDone.empty() ) {
444 for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) {
445 if ( ContextInstType *ctx = dynamic_cast< ContextInstType * >( (*assertion )->get_type() ) ) {
446 for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) {
447 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i );
448 assert( dwt );
449 nextRound.push_back( dwt->clone() );
450 }
451 delete ctx;
452 } else {
453 FixFunction fixer;
454 *assertion = (*assertion )->acceptMutator( fixer );
455 if ( fixer.get_isVoid() ) {
456 throw SemanticError( "invalid type void in assertion of function ", func );
457 }
458 (*type )->get_assertions().push_back( *assertion );
459 } // if
460 } // for
461 toBeDone.clear();
462 toBeDone.splice( toBeDone.end(), nextRound );
463 } // while
464 } // for
465 }
466
467 void Pass3::visit( ObjectDecl *object ) {
468 forallFixer( object->get_type() );
469 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
470 forallFixer( pointer->get_base() );
471 } // if
472 Parent::visit( object );
473 object->fixUniqueId();
474 }
475
476 void Pass3::visit( FunctionDecl *func ) {
477 forallFixer( func->get_type() );
478 Parent::visit( func );
479 func->fixUniqueId();
480 }
481
482 static const std::list< std::string > noLabels;
483
484 void AddStructAssignment::addStructAssignment( std::list< Declaration * > &translationUnit ) {
485 AddStructAssignment visitor;
486 acceptAndAdd( translationUnit, visitor, false );
487 }
488
489 template< typename OutputIterator >
490 void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
491 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
492 // unnamed bit fields are not copied as they cannot be accessed
493 if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
494
495 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
496
497 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
498 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
499
500 // do something special for unnamed members
501 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
502 assignExpr->get_args().push_back( dstselect );
503
504 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
505 assignExpr->get_args().push_back( srcselect );
506
507 *out++ = new ExprStmt( noLabels, assignExpr );
508 }
509
510 template< typename OutputIterator >
511 void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
512 static UniqueName indexName( "_index" );
513
514 // for a flexible array member nothing is done -- user must define own assignment
515 if ( ! array->get_dimension() ) return;
516
517 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
518 *out++ = new DeclStmt( noLabels, index );
519
520 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
521 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
522 init->get_args().push_back( new NameExpr( "0" ) );
523 Statement *initStmt = new ExprStmt( noLabels, init );
524
525 UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
526 cond->get_args().push_back( new VariableExpr( index ) );
527 cond->get_args().push_back( array->get_dimension()->clone() );
528
529 UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
530 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
531
532 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
533
534 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
535 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
536
537 Expression *dstselect = new MemberExpr( member, derefExpr );
538 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
539 dstIndex->get_args().push_back( dstselect );
540 dstIndex->get_args().push_back( new VariableExpr( index ) );
541 assignExpr->get_args().push_back( dstIndex );
542
543 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
544 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
545 srcIndex->get_args().push_back( srcselect );
546 srcIndex->get_args().push_back( new VariableExpr( index ) );
547 assignExpr->get_args().push_back( srcIndex );
548
549 *out++ = new ForStmt( noLabels, initStmt, cond, inc, new ExprStmt( noLabels, assignExpr ) );
550 }
551
552 //E ?=?(E volatile*, int),
553 // ?=?(E _Atomic volatile*, int);
554 void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
555 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
556
557 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
558 assignType->get_returnVals().push_back( returnVal );
559
560 // need two assignment operators with different types
561 FunctionType * assignType2 = assignType->clone();
562
563 // E ?=?(E volatile *, E)
564 Type *etype = refType->clone();
565 // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
566
567 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
568 assignType->get_parameters().push_back( dstParam );
569
570 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
571 assignType->get_parameters().push_back( srcParam );
572
573 // E ?=?(E volatile *, int)
574 assignType2->get_parameters().push_back( dstParam->clone() );
575 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
576 ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
577 assignType2->get_parameters().push_back( srcParam2 );
578
579 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
580 // because each unit generates copies of the default routines for each aggregate.
581
582 // since there is no definition, these should not be inline
583 // make these intrinsic so that the code generator does not make use of them
584 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
585 assignDecl->fixUniqueId();
586 FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
587 assignDecl2->fixUniqueId();
588
589 // these should be built in the same way that the prelude
590 // functions are, so build a list containing the prototypes
591 // and allow MakeLibCfa to autogenerate the bodies.
592 std::list< Declaration * > assigns;
593 assigns.push_back( assignDecl );
594 assigns.push_back( assignDecl2 );
595
596 LibCfa::makeLibCfa( assigns );
597
598 // need to remove the prototypes, since this may be nested in a routine
599 for (int start = 0, end = assigns.size()/2; start < end; start++) {
600 delete assigns.front();
601 assigns.pop_front();
602 }
603
604 declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
605 }
606
607
608 Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
609 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
610
611 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
612 assignType->get_returnVals().push_back( returnVal );
613
614 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType->clone() ), 0 );
615 assignType->get_parameters().push_back( dstParam );
616
617 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType, 0 );
618 assignType->get_parameters().push_back( srcParam );
619
620 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
621 // because each unit generates copies of the default routines for each aggregate.
622 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
623 assignDecl->fixUniqueId();
624
625 for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
626 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
627 // query the type qualifiers of this field and skip assigning it if it is marked const.
628 // If it is an array type, we need to strip off the array layers to find its qualifiers.
629 Type * type = dwt->get_type();
630 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
631 type = at->get_base();
632 }
633
634 if ( type->get_qualifiers().isConst ) {
635 // don't assign const members
636 continue;
637 }
638
639 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
640 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
641 } else {
642 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
643 } // if
644 } // if
645 } // for
646 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
647
648 return assignDecl;
649 }
650
651 Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
652 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
653
654 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
655 assignType->get_returnVals().push_back( returnVal );
656
657 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType->clone() ), 0 );
658 assignType->get_parameters().push_back( dstParam );
659
660 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType, 0 );
661 assignType->get_parameters().push_back( srcParam );
662
663 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
664 // because each unit generates copies of the default routines for each aggregate.
665 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
666 assignDecl->fixUniqueId();
667
668 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
669 copy->get_args().push_back( new VariableExpr( dstParam ) );
670 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
671 copy->get_args().push_back( new SizeofExpr( refType->clone() ) );
672
673 assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
674 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
675
676 return assignDecl;
677 }
678
679 void AddStructAssignment::visit( EnumDecl *enumDecl ) {
680 if ( ! enumDecl->get_members().empty() ) {
681 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
682 // enumInst->set_baseEnum( enumDecl );
683 // declsToAdd.push_back(
684 makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
685 }
686 }
687
688 void AddStructAssignment::visit( StructDecl *structDecl ) {
689 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
690 StructInstType *structInst = new StructInstType( Type::Qualifiers(), structDecl->get_name() );
691 structInst->set_baseStruct( structDecl );
692 declsToAdd.push_back( makeStructAssignment( structDecl, structInst, functionNesting ) );
693 structsDone.insert( structDecl->get_name() );
694 } // if
695 }
696
697 void AddStructAssignment::visit( UnionDecl *unionDecl ) {
698 if ( ! unionDecl->get_members().empty() ) {
699 UnionInstType *unionInst = new UnionInstType( Type::Qualifiers(), unionDecl->get_name() );
700 unionInst->set_baseUnion( unionDecl );
701 declsToAdd.push_back( makeUnionAssignment( unionDecl, unionInst, functionNesting ) );
702 } // if
703 }
704
705 void AddStructAssignment::visit( TypeDecl *typeDecl ) {
706 CompoundStmt *stmts = 0;
707 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
708 typeInst->set_baseType( typeDecl );
709 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
710 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
711 if ( typeDecl->get_base() ) {
712 stmts = new CompoundStmt( std::list< Label >() );
713 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
714 assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
715 assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
716 stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
717 } // if
718 FunctionType *type = new FunctionType( Type::Qualifiers(), false );
719 type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
720 type->get_parameters().push_back( dst );
721 type->get_parameters().push_back( src );
722 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
723 declsToAdd.push_back( func );
724 }
725
726 void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
727 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
728 statements.insert( i, new DeclStmt( noLabels, *decl ) );
729 } // for
730 declsToAdd.clear();
731 }
732
733 void AddStructAssignment::visit( FunctionType *) {
734 // ensure that we don't add assignment ops for types defined as part of the function
735 }
736
737 void AddStructAssignment::visit( PointerType *) {
738 // ensure that we don't add assignment ops for types defined as part of the pointer
739 }
740
741 void AddStructAssignment::visit( ContextDecl *) {
742 // ensure that we don't add assignment ops for types defined as part of the context
743 }
744
745 template< typename StmtClass >
746 inline void AddStructAssignment::visitStatement( StmtClass *stmt ) {
747 std::set< std::string > oldStructs = structsDone;
748 addVisit( stmt, *this );
749 structsDone = oldStructs;
750 }
751
752 void AddStructAssignment::visit( FunctionDecl *functionDecl ) {
753 maybeAccept( functionDecl->get_functionType(), *this );
754 acceptAll( functionDecl->get_oldDecls(), *this );
755 functionNesting += 1;
756 maybeAccept( functionDecl->get_statements(), *this );
757 functionNesting -= 1;
758 }
759
760 void AddStructAssignment::visit( CompoundStmt *compoundStmt ) {
761 visitStatement( compoundStmt );
762 }
763
764 void AddStructAssignment::visit( IfStmt *ifStmt ) {
765 visitStatement( ifStmt );
766 }
767
768 void AddStructAssignment::visit( WhileStmt *whileStmt ) {
769 visitStatement( whileStmt );
770 }
771
772 void AddStructAssignment::visit( ForStmt *forStmt ) {
773 visitStatement( forStmt );
774 }
775
776 void AddStructAssignment::visit( SwitchStmt *switchStmt ) {
777 visitStatement( switchStmt );
778 }
779
780 void AddStructAssignment::visit( ChooseStmt *switchStmt ) {
781 visitStatement( switchStmt );
782 }
783
784 void AddStructAssignment::visit( CaseStmt *caseStmt ) {
785 visitStatement( caseStmt );
786 }
787
788 void AddStructAssignment::visit( CatchStmt *cathStmt ) {
789 visitStatement( cathStmt );
790 }
791
792 bool isTypedef( Declaration *decl ) {
793 return dynamic_cast< TypedefDecl * >( decl );
794 }
795
796 void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
797 EliminateTypedef eliminator;
798 mutateAll( translationUnit, eliminator );
799 filter( translationUnit, isTypedef, true );
800 }
801
802 Type *EliminateTypedef::mutate( TypeInstType *typeInst ) {
803 // instances of typedef types will come here. If it is an instance
804 // of a typdef type, link the instance to its actual type.
805 TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
806 if ( def != typedefNames.end() ) {
807 Type *ret = def->second.first->get_base()->clone();
808 ret->get_qualifiers() += typeInst->get_qualifiers();
809 delete typeInst;
810 return ret;
811 } // if
812 return typeInst;
813 }
814
815 Declaration *EliminateTypedef::mutate( TypedefDecl *tyDecl ) {
816 Declaration *ret = Mutator::mutate( tyDecl );
817 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
818 // typedef to the same name from the same scope
819 // must be from the same type
820
821 Type * t1 = tyDecl->get_base();
822 Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
823 if ( ! typeEquals( t1, t2, true ) ) {
824 throw SemanticError( "cannot redefine typedef: " + tyDecl->get_name() );
825 }
826 } else {
827 typedefNames[ tyDecl->get_name() ] = std::make_pair( tyDecl, scopeLevel );
828 } // if
829
830 // When a typedef is a forward declaration:
831 // typedef struct screen SCREEN;
832 // the declaration portion must be retained:
833 // struct screen;
834 // because the expansion of the typedef is:
835 // void rtn( SCREEN *p ) => void rtn( struct screen *p )
836 // hence the type-name "screen" must be defined.
837 // Note, qualifiers on the typedef are superfluous for the forward declaration.
838 if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( tyDecl->get_base() ) ) {
839 return new StructDecl( aggDecl->get_name() );
840 } else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( tyDecl->get_base() ) ) {
841 return new UnionDecl( aggDecl->get_name() );
842 } else {
843 return ret;
844 } // if
845 }
846
847 TypeDecl *EliminateTypedef::mutate( TypeDecl *typeDecl ) {
848 TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
849 if ( i != typedefNames.end() ) {
850 typedefNames.erase( i ) ;
851 } // if
852 return typeDecl;
853 }
854
855 DeclarationWithType *EliminateTypedef::mutate( FunctionDecl *funcDecl ) {
856 TypedefMap oldNames = typedefNames;
857 DeclarationWithType *ret = Mutator::mutate( funcDecl );
858 typedefNames = oldNames;
859 return ret;
860 }
861
862 ObjectDecl *EliminateTypedef::mutate( ObjectDecl *objDecl ) {
863 TypedefMap oldNames = typedefNames;
864 ObjectDecl *ret = Mutator::mutate( objDecl );
865 typedefNames = oldNames;
866 return ret;
867 }
868
869 Expression *EliminateTypedef::mutate( CastExpr *castExpr ) {
870 TypedefMap oldNames = typedefNames;
871 Expression *ret = Mutator::mutate( castExpr );
872 typedefNames = oldNames;
873 return ret;
874 }
875
876 CompoundStmt *EliminateTypedef::mutate( CompoundStmt *compoundStmt ) {
877 TypedefMap oldNames = typedefNames;
878 scopeLevel += 1;
879 CompoundStmt *ret = Mutator::mutate( compoundStmt );
880 scopeLevel -= 1;
881 std::list< Statement * >::iterator i = compoundStmt->get_kids().begin();
882 while ( i != compoundStmt->get_kids().end() ) {
883 std::list< Statement * >::iterator next = i;
884 ++next;
885 if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( *i ) ) {
886 if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
887 delete *i;
888 compoundStmt->get_kids().erase( i );
889 } // if
890 } // if
891 i = next;
892 } // while
893 typedefNames = oldNames;
894 return ret;
895 }
896} // namespace SymTab
897
898// Local Variables: //
899// tab-width: 4 //
900// mode: c++ //
901// compile-command: "make install" //
902// End: //
Note: See TracBrowser for help on using the repository browser.