Changeset 0a267c1


Ignore:
Timestamp:
Oct 19, 2017, 11:13:12 AM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
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)
Message:

Refactor autogen for UnionDecl? and update 64-bit tests

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    rb4748db r0a267c1  
    578578        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
    579579                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;
    584584
    585585                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();
    587587                assert( t1 );
    588588
     
    604604        }
    605605        FunctionDecl * isDefaultConstructor( Declaration * decl ) {
    606                 if ( isConstructor( decl->get_name() ) ) {
     606                if ( isConstructor( decl->name ) ) {
    607607                        if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
    608                                 if ( func->get_functionType()->get_parameters().size() == 1 ) {
     608                                if ( func->type->parameters.size() == 1 ) {
    609609                                        return func;
    610610                                }
  • src/SymTab/Autogen.cc

    rb4748db r0a267c1  
    105105                std::list< Declaration * > definitions, forwards;
    106106
    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 ) {}
    108108
    109109                virtual bool shouldAutogen() const = 0;
     
    112112        protected:
    113113                Type * type;
     114                const std::vector< FuncData > & data;
    114115                unsigned int functionNesting;
    115                 const std::vector< FuncData > & data;
    116116                SymTab::Indexer & indexer;
    117117
     
    126126                StructDecl * aggregateDecl;
    127127        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) {}
    129129
    130130                virtual bool shouldAutogen() const override;
     
    148148        };
    149149
     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
    150176        class TypeFuncGenerator : public FuncGenerator {
    151177                TypeDecl * typeDecl;
    152178        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 ) {}
    154180
    155181                virtual bool shouldAutogen() const override;
     
    395421                unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
    396422
     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
    397427                // create constructors which take each member type as a parameter.
    398428                // for example, for struct A { int x, y; }; generate
    399429                //   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;
    419445        }
    420446
     
    486512        }
    487513
     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
    488522        /// generate a single union assignment expression (using memcpy)
    489523        template< typename OutputIterator >
    490         void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
     524        void UnionFuncGenerator::makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    491525                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() ) );
    495529                *out++ = new ExprStmt( noLabels, copy );
    496530        }
    497531
    498532        /// 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;
    550562
    551563                // create a constructor which takes the first member type as a parameter.
     
    553565                // void ?{}(A *, int)
    554566                // 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
    567574                                break;
    568575                        }
    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;
    582586        }
    583587
     
    651655                                unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    652656                        }
    653                         makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter, indexer );
     657                        UnionFuncGenerator gen( unionDecl, &unionInst, data, functionNesting, indexer );
     658                        generateFunctions( gen, declsToAddAfter );
    654659                } // if
    655660        }
     
    661666
    662667                TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl );
    663                 TypeFuncGenerator gen( typeDecl, &refType, functionNesting, data, indexer );
     668                TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer );
    664669                generateFunctions( gen, declsToAddAfter );
    665670        }
  • src/tests/.expect/64/extension.txt

    rb4748db r0a267c1  
    6363    __extension__ signed int __c__i_1;
    6464};
     65static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     66static inline void ___constructor__F_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     67static inline void ___destructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     68static inline union U ___operator_assign__F2uU_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     69static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1);
    6570static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1){
    6671}
     
    7681    return ___ret__2uU_1;
    7782}
    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 )));
     83static 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 )));
    8085}
    8186__extension__ enum E {
Note: See TracChangeset for help on using the changeset viewer.