Changeset 0a267c1
- Timestamp:
- Oct 19, 2017, 11:13:12 AM (7 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:
- 18ca28e
- Parents:
- b4748db
- git-author:
- Rob Schluntz <rschlunt@…> (10/13/17 12:38:26)
- git-committer:
- Rob Schluntz <rschlunt@…> (10/19/17 11:13:12)
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
rb4748db r0a267c1 578 578 FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) { 579 579 FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl ); 580 if ( ! function ) return 0;581 if ( function-> get_name() != fname ) return 0;582 FunctionType * ftype = function-> get_functionType();583 if ( ftype-> get_parameters().size() != 2 ) return 0;580 if ( ! function ) return nullptr; 581 if ( function->name != fname ) return nullptr; 582 FunctionType * ftype = function->type; 583 if ( ftype->parameters.size() != 2 ) return nullptr; 584 584 585 585 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 586 Type * t2 = ftype-> get_parameters().back()->get_type();586 Type * t2 = ftype->parameters.back()->get_type(); 587 587 assert( t1 ); 588 588 … … 604 604 } 605 605 FunctionDecl * isDefaultConstructor( Declaration * decl ) { 606 if ( isConstructor( decl-> get_name()) ) {606 if ( isConstructor( decl->name ) ) { 607 607 if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) { 608 if ( func-> get_functionType()->get_parameters().size() == 1 ) {608 if ( func->type->parameters.size() == 1 ) { 609 609 return func; 610 610 } -
src/SymTab/Autogen.cc
rb4748db r0a267c1 105 105 std::list< Declaration * > definitions, forwards; 106 106 107 FuncGenerator( Type * type, unsigned int functionNesting, const std::vector< FuncData > & data, SymTab::Indexer & indexer ) : type( type ), functionNesting( functionNesting ), data( data), indexer( indexer ) {}107 FuncGenerator( Type * type, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : type( type ), data( data ), functionNesting( functionNesting ), indexer( indexer ) {} 108 108 109 109 virtual bool shouldAutogen() const = 0; … … 112 112 protected: 113 113 Type * type; 114 const std::vector< FuncData > & data; 114 115 unsigned int functionNesting; 115 const std::vector< FuncData > & data;116 116 SymTab::Indexer & indexer; 117 117 … … 126 126 StructDecl * aggregateDecl; 127 127 public: 128 StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, functionNesting, data, indexer ), aggregateDecl( aggregateDecl) {}128 StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {} 129 129 130 130 virtual bool shouldAutogen() const override; … … 148 148 }; 149 149 150 class UnionFuncGenerator : public FuncGenerator { 151 UnionDecl * aggregateDecl; 152 public: 153 UnionFuncGenerator( UnionDecl * aggregateDecl, UnionInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {} 154 155 virtual bool shouldAutogen() const override; 156 virtual bool isConcurrentType() const override; 157 158 virtual void genFuncBody( FunctionDecl * dcl ) override; 159 virtual void genFieldCtors() override; 160 161 private: 162 /// generates a single struct member operation (constructor call, destructor call, assignment call) 163 template<typename OutputIterator> 164 void makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ); 165 166 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 167 template<typename Iterator> 168 void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ); 169 170 /// generate the body of a constructor which takes parameters that match fields, e.g. 171 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 172 template<typename Iterator> 173 void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ); 174 }; 175 150 176 class TypeFuncGenerator : public FuncGenerator { 151 177 TypeDecl * typeDecl; 152 178 public: 153 TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, unsigned int functionNesting, const std::vector<FuncData> & data, SymTab::Indexer & indexer ) : FuncGenerator( refType, functionNesting, data, indexer ), typeDecl( typeDecl ) {}179 TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, const std::vector<FuncData> & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), typeDecl( typeDecl ) {} 154 180 155 181 virtual bool shouldAutogen() const override; … … 395 421 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 396 422 423 // Field constructors are only generated if default and copy constructor 424 // are generated, since they need access to both 425 if ( numCtors != 2 ) return; 426 397 427 // create constructors which take each member type as a parameter. 398 428 // for example, for struct A { int x, y; }; generate 399 429 // void ?{}(A *, int) and void ?{}(A *, int, int) 400 // Field constructors are only generated if default and copy constructor 401 // are generated, since they need access to both 402 if ( numCtors == 2 ) { 403 const auto & typeParams = aggregateDecl->parameters; 404 FunctionType * memCtorType = genDefaultType( type ); 405 cloneAll( typeParams, memCtorType->forall ); 406 for ( Declaration * member : aggregateDecl->members ) { 407 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 408 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 409 // don't make a function whose parameter is an unnamed bitfield 410 continue; 411 } 412 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) ); 413 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 414 makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor ); 415 resolve( ctor ); 416 } 417 delete memCtorType; 418 } 430 const auto & typeParams = aggregateDecl->parameters; 431 FunctionType * memCtorType = genDefaultType( type ); 432 cloneAll( typeParams, memCtorType->forall ); 433 for ( Declaration * member : aggregateDecl->members ) { 434 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 435 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 436 // don't make a function whose parameter is an unnamed bitfield 437 continue; 438 } 439 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) ); 440 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 441 makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor ); 442 resolve( ctor ); 443 } 444 delete memCtorType; 419 445 } 420 446 … … 486 512 } 487 513 514 bool UnionFuncGenerator::shouldAutogen() const { 515 // Builtins do not use autogeneration. 516 return ! aggregateDecl->linkage.is_builtin; 517 } 518 519 // xxx - is this right? 520 bool UnionFuncGenerator::isConcurrentType() const { return false; }; 521 488 522 /// generate a single union assignment expression (using memcpy) 489 523 template< typename OutputIterator > 490 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {524 void UnionFuncGenerator::makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 491 525 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 492 copy-> get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) );493 copy-> get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );494 copy-> get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );526 copy->args.push_back( new AddressExpr( new VariableExpr( dstParam ) ) ); 527 copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 528 copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); 495 529 *out++ = new ExprStmt( noLabels, copy ); 496 530 } 497 531 498 532 /// generates the body of a union assignment/copy constructor/field constructor 499 void makeUnionAssignBody( FunctionDecl * funcDecl ) { 500 FunctionType * ftype = funcDecl->get_functionType(); 501 assert( ftype->get_parameters().size() == 2 ); 502 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 503 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 504 505 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) ); 506 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) { 507 // also generate return statement in assignment 508 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 509 } 510 } 511 512 /// generates union constructors, destructors, and assignment operator 513 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, SymTab::Indexer & indexer ) { 514 // Make function polymorphic in same parameters as generic union, if applicable 515 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 516 517 // default ctor/dtor need only first parameter 518 // void ?{}(T *); void ^?{}(T *); 519 FunctionType *ctorType = genDefaultType( refType ); 520 FunctionType *dtorType = genDefaultType( refType ); 521 522 // copy ctor needs both parameters 523 // void ?{}(T *, T); 524 FunctionType *copyCtorType = genCopyType( refType ); 525 526 // assignment needs both and return value 527 // T ?=?(T *, T); 528 FunctionType *assignType = genAssignType( refType ); 529 530 cloneAll( typeParams, ctorType->get_forall() ); 531 cloneAll( typeParams, dtorType->get_forall() ); 532 cloneAll( typeParams, copyCtorType->get_forall() ); 533 cloneAll( typeParams, assignType->get_forall() ); 534 535 // add unused attribute to parameters of default constructor and destructor 536 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 537 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 538 539 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 540 // because each unit generates copies of the default routines for each aggregate. 541 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 542 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 543 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 544 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 545 546 makeUnionAssignBody( assignDecl ); 547 548 // body of assignment and copy ctor is the same 549 makeUnionAssignBody( copyCtorDecl ); 533 void UnionFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) { 534 FunctionType * ftype = funcDecl->type; 535 if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) { 536 assert( ftype->parameters.size() == 2 ); 537 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 538 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() ); 539 540 makeMemberOp( srcParam, dstParam, back_inserter( funcDecl->statements->kids ) ); 541 if ( CodeGen::isAssignment( funcDecl->name ) ) { 542 // also generate return statement in assignment 543 funcDecl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 544 } 545 } else { 546 // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings 547 assert( ftype->parameters.size() == 1 ); 548 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 549 dstParam->attributes.push_back( new Attribute( "unused" ) ); 550 } 551 } 552 553 /// generate the body of a constructor which takes parameters that match fields, e.g. 554 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 555 void UnionFuncGenerator::genFieldCtors() { 556 // field ctors are only generated if default constructor and copy constructor are both generated 557 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 558 559 // Field constructors are only generated if default and copy constructor 560 // are generated, since they need access to both 561 if ( numCtors != 2 ) return; 550 562 551 563 // create a constructor which takes the first member type as a parameter. … … 553 565 // void ?{}(A *, int) 554 566 // This is to mimic C's behaviour which initializes the first member of the union. 555 std::list<Declaration *> memCtors; 556 for ( Declaration * member : aggregateDecl->get_members() ) { 557 if ( DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member ) ) { 558 ObjectDecl * srcParam = new ObjectDecl( "src", Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ); 559 560 FunctionType * memCtorType = ctorType->clone(); 561 memCtorType->get_parameters().push_back( srcParam ); 562 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting ); 563 564 makeUnionAssignBody( ctor ); 565 memCtors.push_back( ctor ); 566 // only generate a ctor for the first field 567 const auto & typeParams = aggregateDecl->parameters; 568 FunctionType * memCtorType = genDefaultType( type ); 569 cloneAll( typeParams, memCtorType->forall ); 570 for ( Declaration * member : aggregateDecl->members ) { 571 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 572 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 573 // don't make a function whose parameter is an unnamed bitfield 567 574 break; 568 575 } 569 } 570 571 declsToAdd.push_back( ctorDecl ); 572 declsToAdd.push_back( copyCtorDecl ); 573 declsToAdd.push_back( dtorDecl ); 574 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 575 576 indexer.addId( ctorDecl ); 577 indexer.addId( copyCtorDecl ); 578 indexer.addId( dtorDecl ); 579 indexer.addId( assignDecl ); 580 581 declsToAdd.splice( declsToAdd.end(), memCtors ); 576 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, field->get_type()->clone(), nullptr ) ); 577 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 578 ObjectDecl * srcParam = strict_dynamic_cast<ObjectDecl *>( ctor->type->parameters.back() ); 579 ObjectDecl * dstParam = InitTweak::getParamThis( ctor->type ); 580 makeMemberOp( srcParam, dstParam, back_inserter( ctor->statements->kids ) ); 581 resolve( ctor ); 582 // only generate one field ctor for unions 583 break; 584 } 585 delete memCtorType; 582 586 } 583 587 … … 651 655 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 652 656 } 653 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter, indexer ); 657 UnionFuncGenerator gen( unionDecl, &unionInst, data, functionNesting, indexer ); 658 generateFunctions( gen, declsToAddAfter ); 654 659 } // if 655 660 } … … 661 666 662 667 TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl ); 663 TypeFuncGenerator gen( typeDecl, &refType, functionNesting, data, indexer );668 TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer ); 664 669 generateFunctions( gen, declsToAddAfter ); 665 670 } -
src/tests/.expect/64/extension.txt
rb4748db r0a267c1 63 63 __extension__ signed int __c__i_1; 64 64 }; 65 static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1); 66 static inline void ___constructor__F_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1); 67 static inline void ___destructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1); 68 static inline union U ___operator_assign__F2uU_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1); 69 static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1); 65 70 static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1){ 66 71 } … … 76 81 return ___ret__2uU_1; 77 82 } 78 static inline void ___constructor__F_R2uUi_autogen___1( __attribute__ ((unused)) union U *___dst__R2uU_1, signed int __src__i_1){79 ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__ src__i_1)), sizeof(signed int )));83 static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1){ 84 ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__a__i_1)), sizeof(signed int ))); 80 85 } 81 86 __extension__ enum E {
Note: See TracChangeset
for help on using the changeset viewer.