Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r98735ef ra9a259c  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan 27 22:03:12 2016
    13 // Update Count     : 225
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Mon Feb 22 12:26:37 2016
     13// Update Count     : 297
    1414//
    1515
     
    202202        };
    203203
     204        class VerifyCtorDtor : public Visitor {
     205        public:
     206                /// ensure that constructors and destructors have at least one
     207                /// parameter, the first of which must be a pointer, and no
     208                /// return values.
     209                static void verify( std::list< Declaration * > &translationUnit );
     210
     211                // VerifyCtorDtor() {}
     212
     213                virtual void visit( FunctionDecl *funcDecl );
     214        private:
     215        };
     216
    204217        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    205218                Pass1 pass1;
     
    213226                AutogenerateRoutines::autogenerateRoutines( translationUnit );
    214227                acceptAll( translationUnit, pass3 );
     228                VerifyCtorDtor::verify( translationUnit );
    215229        }
    216230
     
    521535
    522536        template< typename OutputIterator >
    523         void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
     537        void makeScalarFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
    524538                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
    525539                // unnamed bit fields are not copied as they cannot be accessed
    526540                if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
    527541
    528                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
     542                // want to be able to generate assignment, ctor, and dtor generically,
     543                // so fname is either ?=?, ?{}, or ^?{}
     544                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    529545
    530546                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     
    533549                // do something special for unnamed members
    534550                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
    535                 assignExpr->get_args().push_back( dstselect );
     551                fExpr->get_args().push_back( dstselect );
    536552
    537553                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    538                 assignExpr->get_args().push_back( srcselect );
    539 
    540                 *out++ = new ExprStmt( noLabels, assignExpr );
     554                fExpr->get_args().push_back( srcselect );
     555
     556                *out++ = new ExprStmt( noLabels, fExpr );
    541557        }
    542558
    543559        template< typename OutputIterator >
    544         void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
     560        void makeArrayFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, std::string fname, OutputIterator out ) {
    545561                static UniqueName indexName( "_index" );
    546562
     
    565581                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    566582
    567                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
     583                // want to be able to generate assignment, ctor, and dtor generically,
     584                // so fname is either ?=?, ?{}, or ^?{}
     585                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    568586
    569587                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     
    574592                dstIndex->get_args().push_back( dstselect );
    575593                dstIndex->get_args().push_back( new VariableExpr( index ) );
    576                 assignExpr->get_args().push_back( dstIndex );
     594                fExpr->get_args().push_back( dstIndex );
    577595
    578596                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
     
    580598                srcIndex->get_args().push_back( srcselect );
    581599                srcIndex->get_args().push_back( new VariableExpr( index ) );
    582                 assignExpr->get_args().push_back( srcIndex );
    583 
    584                 *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
     600                fExpr->get_args().push_back( srcIndex );
     601
     602                *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) );
    585603        }
    586604
     
    732750                                        // assign to both destination and return value
    733751                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
    734                                                 makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    735                                                 makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     752                                                makeArrayFunction( srcParam, dstParam, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
     753                                                makeArrayFunction( srcParam, returnVal, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
    736754                                        } else {
    737                                                 makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
    738                                                 makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
     755                                                makeScalarFunction( srcParam, dstParam, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
     756                                                makeScalarFunction( srcParam, returnVal, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
    739757                                        } // if
    740758                                } else {
    741759                                        // assign to destination
    742760                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
    743                                                 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     761                                                makeArrayFunction( srcParam, dstParam, dwt, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
    744762                                        } else {
    745                                                 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     763                                                makeScalarFunction( srcParam, dstParam, dwt, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
    746764                                        } // if
    747765                                } // if
     
    753771        }
    754772
    755         Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
     773        void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
     774                FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );
     775
     776                // Make function polymorphic in same parameters as generic struct, if applicable
     777                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
     778                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
     779                std::list< Expression* > structParams;  // List of matching parameters to put on types
     780                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
     781                        isGeneric = true;
     782                        TypeDecl *typeParam = (*param)->clone();
     783                        ctorType->get_forall().push_back( typeParam );
     784                        structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     785                }
     786
     787                ObjectDecl *thisParam = new ObjectDecl( "_this", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
     788                ctorType->get_parameters().push_back( thisParam );
     789
     790                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     791                // because each unit generates copies of the default routines for each aggregate.
     792                FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );
     793                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
     794                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
     795                ctorDecl->fixUniqueId();
     796                copyCtorDecl->fixUniqueId();
     797                dtorDecl->fixUniqueId();
     798
     799                // add definitions
     800                // TODO: add in calls to default constructors and destructors for fields
     801                ctorDecl->set_statements( new CompoundStmt( noLabels ) );
     802                copyCtorDecl->set_statements( new CompoundStmt( noLabels ) );
     803                dtorDecl->set_statements( new CompoundStmt( noLabels ) );
     804                declsToAdd.push_back( ctorDecl );
     805                declsToAdd.push_back( copyCtorDecl );
     806                declsToAdd.push_back( dtorDecl );
     807
     808                ObjectDecl * srcParam = new ObjectDecl( "_other", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     809                copyCtorDecl->get_functionType()->get_parameters().push_back( srcParam );
     810                for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
     811                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
     812                                // query the type qualifiers of this field and skip assigning it if it is marked const.
     813                                // If it is an array type, we need to strip off the array layers to find its qualifiers.
     814                                Type * type = dwt->get_type();
     815                                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     816                                        type = at->get_base();
     817                                }
     818
     819                                if ( type->get_qualifiers().isConst ) {
     820                                        // don't assign const members
     821                                        continue;
     822                                }
     823
     824                                if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
     825                                        makeArrayFunction( srcParam, thisParam, dwt, array, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
     826                                        // if ( isGeneric ) makeArrayFunction( srcParam, returnVal, dwt, array, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
     827                                } else {
     828                                        makeScalarFunction( srcParam, thisParam, dwt, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
     829                                        // if ( isGeneric ) makeScalarCtor( srcParam, returnVal, dwt, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
     830                                } // if
     831                        } // if
     832                } // for
     833                // if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     834        }
     835
     836        void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
    756837                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    757838
     
    767848                }
    768849
     850                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
     851                assignType->get_parameters().push_back( dstParam );
     852
     853                // default ctor/dtor need only first parameter
     854                FunctionType * ctorType = assignType->clone();
     855                FunctionType * dtorType = assignType->clone();
     856
     857                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
     858                assignType->get_parameters().push_back( srcParam );
     859
     860                // copy ctor needs both parameters
     861                FunctionType * copyCtorType = assignType->clone();
     862
     863                // assignment needs both and return value
    769864                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    770865                assignType->get_returnVals().push_back( returnVal );
    771 
    772                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
    773                 assignType->get_parameters().push_back( dstParam );
    774 
    775                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    776                 assignType->get_parameters().push_back( srcParam );
    777866
    778867                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    779868                // because each unit generates copies of the default routines for each aggregate.
    780869                FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
     870                FunctionDecl *ctorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
     871                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false );
     872                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
     873
    781874                assignDecl->fixUniqueId();
     875                ctorDecl->fixUniqueId();
     876                copyCtorDecl->fixUniqueId();
     877                dtorDecl->fixUniqueId();
    782878
    783879                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    784880                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    785                
     881
    786882                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    787883
    788                 return assignDecl;
     884                // body of assignment and copy ctor is the same
     885                copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
     886
     887                declsToAdd.push_back( assignDecl );
     888                declsToAdd.push_back( ctorDecl );
     889                declsToAdd.push_back( copyCtorDecl );
     890                declsToAdd.push_back( dtorDecl );
    789891        }
    790892
     
    802904                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    803905                        structInst.set_baseStruct( structDecl );
     906
    804907                        declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
     908                        makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
    805909                        structsDone.insert( structDecl->get_name() );
    806910                } // if
     
    811915                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    812916                        unionInst.set_baseUnion( unionDecl );
    813                         declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
     917                        makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
    814918                } // if
    815919        }
     
    10801184        }
    10811185
     1186        void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
     1187                VerifyCtorDtor verifier;
     1188                acceptAll( translationUnit, verifier );
     1189        }
     1190
     1191        void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
     1192                FunctionType * funcType = funcDecl->get_functionType();
     1193                std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
     1194                std::list< DeclarationWithType * > &params = funcType->get_parameters();
     1195
     1196                if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
     1197                        if ( params.size() == 0 ) {
     1198                                throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
     1199                        }
     1200                        if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
     1201                                throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
     1202                        }
     1203                        if ( returnVals.size() != 0 ) {
     1204                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
     1205                        }
     1206                }
     1207
     1208                Visitor::visit( funcDecl );
     1209                // original idea: modify signature of ctor/dtors and insert appropriate return statements
     1210                // to cause desired behaviour
     1211                // new idea: add comma exprs to every ctor call to produce first parameter.
     1212                // this requires some memoization of the first parameter, because it can be a
     1213                // complicated expression with side effects (see: malloc). idea: add temporary variable
     1214                // that is assigned address of constructed object in ctor argument position and
     1215                // return the temporary. It should also be done after all implicit ctors are
     1216                // added, so not in this pass!
     1217        }
    10821218} // namespace SymTab
    10831219
Note: See TracChangeset for help on using the changeset viewer.