Changeset 207c7e1d for src/SymTab
- Timestamp:
- Jan 23, 2017, 11:42:09 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 092528b
- Parents:
- bd98b58
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
rbd98b58 r207c7e1d 25 25 #include "Autogen.h" 26 26 #include "GenPoly/ScopedSet.h" 27 #include "Common/ScopedMap.h" 27 28 #include "SymTab/Mangler.h" 28 29 #include "GenPoly/DeclMutator.h" … … 30 31 namespace SymTab { 31 32 Type * SizeType = 0; 32 33 class AutogenerateRoutines : public Visitor { 33 typedef ScopedMap< std::string, bool > TypeMap; 34 35 /// Data used to generate functions generically. Specifically, the name of the generated function, a function which generates the routine protoype, and a map which contains data to determine whether a function should be generated. 36 struct FuncData { 37 typedef FunctionType * (*TypeGen)( Type * ); 38 FuncData( const std::string & fname, const TypeGen & genType, TypeMap & map ) : fname( fname ), genType( genType ), map( map ) {} 39 std::string fname; 40 TypeGen genType; 41 TypeMap & map; 42 }; 43 44 class AutogenerateRoutines final : public Visitor { 34 45 public: 35 46 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; } … … 37 48 typedef Visitor Parent; 38 49 using Parent::visit; 50 51 AutogenerateRoutines(); 39 52 40 53 virtual void visit( EnumDecl *enumDecl ); … … 57 70 std::set< std::string > structsDone; 58 71 unsigned int functionNesting = 0; // current level of nested functions 72 /// Note: the following maps could be ScopedSets, but it should be easier to work 73 /// deleted functions in if they are maps, since the value false can be inserted 74 /// at the current scope without affecting outer scopes or requiring copies. 75 TypeMap copyable, assignable, constructable, destructable; 76 std::vector< FuncData > data; 59 77 }; 60 78 … … 144 162 decl->fixUniqueId(); 145 163 return decl; 164 } 165 166 /// inserts base type of first argument into map if pred(funcDecl) is true 167 void insert( FunctionDecl *funcDecl, TypeMap & map, FunctionDecl * (*pred)(Declaration *) ) { 168 // insert type into constructable, etc. map if appropriate 169 if ( pred( funcDecl ) ) { 170 FunctionType * ftype = funcDecl->get_functionType(); 171 assert( ! ftype->get_parameters().empty() ); 172 Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base(); 173 map.insert( Mangler::mangleType( t ), true ); 174 } 175 } 176 177 /// using map and t, determines if is constructable, etc. 178 bool lookup( const TypeMap & map, Type * t ) { 179 if ( dynamic_cast< PointerType * >( t ) ) { 180 // will need more complicated checking if we want this to work with pointer types, since currently 181 return true; 182 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) { 183 // an array's constructor, etc. is generated on the fly based on the base type's constructor, etc. 184 return lookup( map, at->get_base() ); 185 } 186 TypeMap::const_iterator it = map.find( Mangler::mangleType( t ) ); 187 if ( it != map.end() ) return it->second; 188 // something that does not appear in the map is by default not constructable, etc. 189 return false; 190 } 191 192 /// using map and aggr, examines each member to determine if constructor, etc. should be generated 193 template<typename AggrDecl> 194 bool shouldGenerate( const TypeMap & map, AggrDecl * aggr ) { 195 for ( Declaration * dcl : aggr->get_members() ) { 196 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( dcl ) ) { 197 if ( ! lookup( map, dwt->get_type() ) ) return false; 198 } 199 } 200 return true; 201 } 202 203 /// data structure for abstracting the generation of special functions 204 template< typename OutputIterator > 205 struct FuncGenerator { 206 StructDecl *aggregateDecl; 207 StructInstType *refType; 208 unsigned int functionNesting; 209 const std::list< TypeDecl* > & typeParams; 210 OutputIterator out; 211 FuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : aggregateDecl( aggregateDecl ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {} 212 213 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map. 214 void gen( const FuncData & data ) { 215 if ( ! shouldGenerate( data.map, aggregateDecl ) ) return; 216 FunctionType * ftype = data.genType( refType ); 217 cloneAll( typeParams, ftype->get_forall() ); 218 *out++ = genFunc( data.fname, ftype, functionNesting ); 219 data.map.insert( Mangler::mangleType( refType ), true ); 220 } 221 }; 222 223 template< typename OutputIterator > 224 FuncGenerator<OutputIterator> makeFuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) { 225 return FuncGenerator<OutputIterator>( aggregateDecl, refType, functionNesting, typeParams, out ); 146 226 } 147 227 … … 308 388 309 389 /// generates struct constructors, destructor, and assignment functions 310 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 311 390 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) { 312 391 // Make function polymorphic in same parameters as generic struct, if applicable 313 392 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 314 393 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 315 394 316 // T ?=?(T *, T); 317 FunctionType *assignType = genAssignType( refType ); 318 cloneAll( typeParams, assignType->get_forall() ); 319 320 // void ?{}(T *); void ^?{}(T *); 321 FunctionType *ctorType = genDefaultType( refType ); 322 cloneAll( typeParams, ctorType->get_forall() ); 323 FunctionType *dtorType = genDefaultType( refType ); 324 cloneAll( typeParams, dtorType->get_forall() ); 325 326 // void ?{}(T *, T); 327 FunctionType *copyCtorType = genCopyType( refType ); 328 cloneAll( typeParams, copyCtorType->get_forall() ); 329 330 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 331 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 332 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 333 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 395 // generate each of the functions based on the supplied FuncData objects 396 std::list< FunctionDecl * > newFuncs; 397 auto generator = makeFuncGenerator( aggregateDecl, refType, functionNesting, typeParams, back_inserter( newFuncs ) ); 398 for ( const FuncData & d : data ) { 399 generator.gen( d ); 400 } 401 // field ctors are only generated if default constructor and copy constructor are both generated 402 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } ); 334 403 335 404 if ( functionNesting == 0 ) { … … 338 407 // Note: this is necessary if we want structs which contain 339 408 // generic (otype) structs as members. 340 addForwardDecl( assignDecl, declsToAdd ); 341 addForwardDecl( ctorDecl, declsToAdd ); 342 addForwardDecl( copyCtorDecl, declsToAdd ); 343 addForwardDecl( dtorDecl, declsToAdd ); 409 for ( FunctionDecl * dcl : newFuncs ) { 410 addForwardDecl( dcl, declsToAdd ); 411 } 412 } 413 414 for ( FunctionDecl * dcl : newFuncs ) { 415 // generate appropriate calls to member ctor, assignment 416 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 417 if ( ! InitTweak::isDestructor( dcl->get_name() ) ) { 418 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout ); 419 } else { 420 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false ); 421 } 422 if ( InitTweak::isAssignment( dcl->get_name() ) ) { 423 // assignment needs to return a value 424 FunctionType * assignType = dcl->get_functionType(); 425 assert( assignType->get_parameters().size() == 2 ); 426 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 427 dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 428 } 429 declsToAdd.push_back( dcl ); 344 430 } 345 431 346 432 // create constructors which take each member type as a parameter. 347 433 // for example, for struct A { int x, y; }; generate 348 // void ?{}(A *, int) and void ?{}(A *, int, int) 349 std::list<Declaration *> memCtors; 350 FunctionType * memCtorType = ctorType->clone(); 351 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) { 352 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i ); 353 assert( member ); 354 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) { 355 // don't make a function whose parameter is an unnamed bitfield 356 continue; 357 } else if ( member->get_name() == "" ) { 358 // don't assign to anonymous members 359 // xxx - this is a temporary fix. Anonymous members tie into 360 // our inheritance model. I think the correct way to handle this is to 361 // cast the structure to the type of the member and let the resolver 362 // figure out whether it's valid and have a pass afterwards that fixes 363 // the assignment to use pointer arithmetic with the offset of the 364 // member, much like how generic type members are handled. 365 continue; 366 } 367 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 368 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 369 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout ); 370 memCtors.push_back( ctor ); 371 } 372 delete memCtorType; 373 374 // generate appropriate calls to member ctor, assignment 375 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout ); 376 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout ); 377 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout ); 378 // needs to do everything in reverse, so pass "forward" as false 379 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false ); 380 381 assert( assignType->get_parameters().size() == 2 ); 382 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 383 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 384 385 declsToAdd.push_back( ctorDecl ); 386 declsToAdd.push_back( copyCtorDecl ); 387 declsToAdd.push_back( dtorDecl ); 388 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 389 declsToAdd.splice( declsToAdd.end(), memCtors ); 434 // void ?{}(A *, int) and void ?{}(A *, int, int) 435 // Field constructors are only generated if default and copy constructor 436 // are generated, since they need access to both 437 if ( numCtors == 2 ) { 438 FunctionType * memCtorType = genDefaultType( refType ); 439 cloneAll( typeParams, memCtorType->get_forall() ); 440 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) { 441 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i ); 442 assert( member ); 443 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) { 444 // don't make a function whose parameter is an unnamed bitfield 445 continue; 446 } else if ( member->get_name() == "" ) { 447 // don't assign to anonymous members 448 // xxx - this is a temporary fix. Anonymous members tie into 449 // our inheritance model. I think the correct way to handle this is to 450 // cast the structure to the type of the member and let the resolver 451 // figure out whether it's valid and have a pass afterwards that fixes 452 // the assignment to use pointer arithmetic with the offset of the 453 // member, much like how generic type members are handled. 454 continue; 455 } 456 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 457 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 458 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout ); 459 declsToAdd.push_back( ctor ); 460 } 461 delete memCtorType; 462 } 390 463 } 391 464 … … 481 554 } 482 555 556 AutogenerateRoutines::AutogenerateRoutines() { 557 // the order here determines the order that these functions are generated. 558 // assignment should come last since it uses copy constructor in return. 559 data.push_back( FuncData( "?{}", genDefaultType, constructable ) ); 560 data.push_back( FuncData( "?{}", genCopyType, copyable ) ); 561 data.push_back( FuncData( "^?{}", genDefaultType, destructable ) ); 562 data.push_back( FuncData( "?=?", genAssignType, assignable ) ); 563 } 564 483 565 void AutogenerateRoutines::visit( EnumDecl *enumDecl ) { 484 566 if ( ! enumDecl->get_members().empty() ) { … … 491 573 492 574 void AutogenerateRoutines::visit( StructDecl *structDecl ) { 493 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {575 if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) { 494 576 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 495 577 for ( TypeDecl * typeDecl : structDecl->get_parameters() ) { 578 // need to visit assertions so that they are added to the appropriate maps 579 acceptAll( typeDecl->get_assertions(), *this ); 496 580 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 497 581 } 498 582 structInst.set_baseStruct( structDecl ); 499 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );583 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd, data ); 500 584 structsDone.insert( structDecl->get_name() ); 501 585 } // if … … 564 648 565 649 void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) { 650 // record the existence of this function as appropriate 651 insert( functionDecl, constructable, InitTweak::isDefaultConstructor ); 652 insert( functionDecl, assignable, InitTweak::isAssignment ); 653 insert( functionDecl, copyable, InitTweak::isCopyConstructor ); 654 insert( functionDecl, destructable, InitTweak::isDestructor ); 655 566 656 maybeAccept( functionDecl->get_functionType(), *this ); 567 657 acceptAll( functionDecl->get_oldDecls(), *this ); … … 572 662 573 663 void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) { 664 constructable.beginScope(); 665 assignable.beginScope(); 666 copyable.beginScope(); 667 destructable.beginScope(); 574 668 visitStatement( compoundStmt ); 669 constructable.endScope(); 670 assignable.endScope(); 671 copyable.endScope(); 672 destructable.endScope(); 575 673 } 576 674
Note: See TracChangeset
for help on using the changeset viewer.