Changeset 189d800 for src/SymTab
- Timestamp:
- Oct 19, 2017, 11:13:11 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:
- bfd4974
- Parents:
- bd7e609
- git-author:
- Rob Schluntz <rschlunt@…> (10/11/17 17:20:30)
- git-committer:
- Rob Schluntz <rschlunt@…> (10/19/17 11:13:11)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
rbd7e609 r189d800 54 54 }; 55 55 56 struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting {56 struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting, public WithIndexer { 57 57 AutogenerateRoutines(); 58 58 … … 194 194 Type *refType; 195 195 unsigned int functionNesting; 196 const std::list< TypeDecl* > & typeParams;197 196 OutputIterator out; 198 FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {} 197 FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), out( out ) {} 198 199 const std::list< TypeDecl * > getGenericParams( Type * t ) { 200 std::list< TypeDecl * > * ret = nullptr; 201 if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) { 202 ret = inst->get_baseParameters(); 203 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 204 ret = inst->get_baseParameters(); 205 } 206 return ret ? *ret : std::list< TypeDecl * >(); 207 } 199 208 200 209 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map. 201 210 void gen( const FuncData & data, bool concurrent_type ) { 202 if ( ! shouldGenerate( data.map, container ) ) return; 211 // Make function polymorphic in same parameters as generic struct, if applicable 212 std::list< TypeDecl * > typeParams = getGenericParams( refType ); // List of type variables to be placed on the generated functions 213 203 214 FunctionType * ftype = data.genType( refType ); 204 215 … … 214 225 215 226 template< typename OutputIterator, typename Container > 216 FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams,OutputIterator out ) {217 return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, typeParams,out );227 FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, OutputIterator out ) { 228 return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, out ); 218 229 } 219 230 … … 243 254 // E ?=?(E volatile*, int), 244 255 // ?=?(E _Atomic volatile*, int); 245 void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {256 void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd, SymTab::Indexer & indexer ) { 246 257 247 258 // T ?=?(E *, E); … … 278 289 declsToAdd.push_back( dtorDecl ); 279 290 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 291 292 indexer.addId( ctorDecl ); 293 indexer.addId( copyCtorDecl ); 294 indexer.addId( dtorDecl ); 295 indexer.addId( assignDecl ); 280 296 } 281 297 … … 306 322 } 307 323 308 if ( field->get_name() == "" ) {309 // don't assign to anonymous members310 // xxx - this is a temporary fix. Anonymous members tie into311 // our inheritance model. I think the correct way to handle this is to312 // cast the structure to the type of the member and let the resolver313 // figure out whether it's valid and have a pass afterwards that fixes314 // the assignment to use pointer arithmetic with the offset of the315 // member, much like how generic type members are handled.316 continue;317 }318 319 324 assert( ! func->get_functionType()->get_parameters().empty() ); 320 325 ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() ); … … 348 353 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 349 354 // don't make a function whose parameter is an unnamed bitfield 350 continue;351 } else if ( field->get_name() == "" ) {352 // don't assign to anonymous members353 // xxx - this is a temporary fix. Anonymous members tie into354 // our inheritance model. I think the correct way to handle this is to355 // cast the structure to the type of the member and let the resolver356 // figure out whether it's valid and have a pass afterwards that fixes357 // the assignment to use pointer arithmetic with the offset of the358 // member, much like how generic type members are handled.359 355 continue; 360 356 } else if ( parameter != params.end() ) { … … 379 375 380 376 /// generates struct constructors, destructor, and assignment functions 381 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {377 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data, SymTab::Indexer & indexer ) { 382 378 // Builtins do not use autogeneration. 383 379 if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) { … … 385 381 } 386 382 387 // Make function polymorphic in same parameters as generic struct, if applicable388 const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions389 390 383 // generate each of the functions based on the supplied FuncData objects 391 384 std::list< FunctionDecl * > newFuncs; 392 385 // structure that iterates aggregate decl members, returning their types 393 auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, typeParams,back_inserter( newFuncs ) );386 auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, back_inserter( newFuncs ) ); 394 387 for ( const FuncData & d : data ) { 395 388 generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() ); 396 389 } 397 390 398 // field ctors are only generated if default constructor and copy constructor are both generated 399 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 400 401 if ( functionNesting == 0 ) { 402 // forward declare if top-level struct, so that 403 // type is complete as soon as its body ends 404 // Note: this is necessary if we want structs which contain 405 // generic (otype) structs as members. 406 for ( FunctionDecl * dcl : newFuncs ) { 407 addForwardDecl( dcl, declsToAdd ); 408 } 409 } 410 391 std::list< Declaration * > definitions, forwards; 411 392 for ( FunctionDecl * dcl : newFuncs ) { 412 393 // generate appropriate calls to member ctor, assignment 413 394 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 414 395 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) { 415 makeStructFunctionBody( aggregateDecl-> get_members().begin(), aggregateDecl->get_members().end(), dcl );396 makeStructFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl ); 416 397 } else { 417 makeStructFunctionBody( aggregateDecl-> get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false );418 } 419 if ( CodeGen::isAssignment( dcl-> get_name()) ) {398 makeStructFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false ); 399 } 400 if ( CodeGen::isAssignment( dcl->name ) ) { 420 401 // assignment needs to return a value 421 402 FunctionType * assignType = dcl->get_functionType(); 422 assert( assignType->get_parameters().size() == 2 ); 423 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 424 dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 425 } 426 declsToAdd.push_back( dcl ); 427 } 403 assert( assignType->parameters.size() == 2 ); 404 assert( assignType->returnVals.size() == 1 ); 405 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() ); 406 ObjectDecl * retParam = strict_dynamic_cast< ObjectDecl * >( assignType->returnVals.front() ); 407 408 dcl->statements->push_back( new ExprStmt( noLabels, new UntypedExpr( new NameExpr("?{}"), { new VariableExpr( retParam ), new VariableExpr( srcParam ) } ) ) ); 409 dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( retParam ) ) ); 410 } 411 412 try { 413 ResolvExpr::resolveDecl( dcl, indexer ); 414 } catch ( SemanticError err ) { 415 // okay if decl does not resolve - that means the function should not be generated 416 delete dcl; 417 continue; 418 } 419 420 if ( functionNesting == 0 ) { 421 // forward declare if top-level struct, so that 422 // type is complete as soon as its body ends 423 // Note: this is necessary if we want structs which contain 424 // generic (otype) structs as members. 425 addForwardDecl( dcl, forwards ); 426 } 427 definitions.push_back( dcl ); 428 indexer.addId( dcl ); 429 } 430 431 // field ctors are only generated if default constructor and copy constructor are both generated 432 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 428 433 429 434 // create constructors which take each member type as a parameter. … … 433 438 // are generated, since they need access to both 434 439 if ( numCtors == 2 ) { 440 const auto & typeParams = aggregateDecl->parameters; 435 441 FunctionType * memCtorType = genDefaultType( refType ); 436 cloneAll( typeParams, memCtorType-> get_forall());437 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i) {438 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i);439 assert( member);440 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member) ) ) {442 cloneAll( typeParams, memCtorType->forall ); 443 for ( Declaration * member : aggregateDecl->members ) { 444 DeclarationWithType * field = dynamic_cast<DeclarationWithType *>( member ); 445 assert( field ); 446 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 441 447 // don't make a function whose parameter is an unnamed bitfield 442 448 continue; 443 } else if ( member->get_name() == "" ) { 444 // don't assign to anonymous members 445 // xxx - this is a temporary fix. Anonymous members tie into 446 // our inheritance model. I think the correct way to handle this is to 447 // cast the structure to the type of the member and let the resolver 448 // figure out whether it's valid/choose the correct unnamed member 449 } 450 memCtorType->get_parameters().push_back( new ObjectDecl( field->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) ); 451 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 452 makeStructFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor ); 453 454 try { 455 ResolvExpr::resolveDecl( ctor, indexer ); 456 } catch ( SemanticError err ) { 457 // okay if decl does not resolve - that means the function should not be generated 458 delete ctor; 449 459 continue; 450 460 } 451 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 452 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 453 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor ); 454 declsToAdd.push_back( ctor ); 461 definitions.push_back( ctor ); 455 462 } 456 463 delete memCtorType; 457 464 } 465 466 declsToAdd.splice( declsToAdd.end(), forwards ); 467 declsToAdd.splice( declsToAdd.end(), definitions ); 458 468 } 459 469 … … 483 493 484 494 /// generates union constructors, destructors, and assignment operator 485 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {495 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, SymTab::Indexer & indexer ) { 486 496 // Make function polymorphic in same parameters as generic union, if applicable 487 497 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions … … 545 555 declsToAdd.push_back( dtorDecl ); 546 556 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 557 558 indexer.addId( ctorDecl ); 559 indexer.addId( copyCtorDecl ); 560 indexer.addId( dtorDecl ); 561 indexer.addId( assignDecl ); 562 547 563 declsToAdd.splice( declsToAdd.end(), memCtors ); 548 564 } … … 558 574 559 575 void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) { 560 visit_children = false;561 if ( ! enumDecl->get_members().empty() ) {576 // must visit children (enum constants) to add them to the indexer 577 if ( enumDecl->has_body() ) { 562 578 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() ); 563 //enumInst->set_baseEnum( enumDecl );564 makeEnumFunctions( enumInst, functionNesting, declsToAddAfter );579 enumInst->set_baseEnum( enumDecl ); 580 makeEnumFunctions( enumInst, functionNesting, declsToAddAfter, indexer ); 565 581 } 566 582 } … … 572 588 for ( TypeDecl * typeDecl : structDecl->parameters ) { 573 589 // need to visit assertions so that they are added to the appropriate maps 574 acceptAll( typeDecl->assertions, *visitor );590 // acceptAll( typeDecl->assertions, *visitor ); 575 591 structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) ); 576 592 } 577 593 structInst.set_baseStruct( structDecl ); 578 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );594 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data, indexer ); 579 595 structsDone.insert( structDecl->name ); 580 596 } // if … … 583 599 void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) { 584 600 visit_children = false; 585 if ( ! unionDecl->get_members().empty()) {601 if ( unionDecl->has_body() /* && unionsDone.find( unionDecl->name ) == unionsDone.end() */ ) { 586 602 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 587 603 unionInst.set_baseUnion( unionDecl ); … … 589 605 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 590 606 } 591 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter );607 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter, indexer ); 592 608 } // if 593 609 } … … 608 624 std::list< FunctionDecl * > newFuncs; 609 625 std::list< Declaration * > tds { typeDecl }; 610 std::list< TypeDecl * > typeParams;611 626 TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl ); 612 auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, typeParams,back_inserter( newFuncs ) );627 auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, back_inserter( newFuncs ) ); 613 628 for ( const FuncData & d : data ) { 614 629 generator.gen( d, false );
Note:
See TracChangeset
for help on using the changeset viewer.