Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r620cb95 r4040425  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Mon Feb 22 12:26:37 2016
    13 // Update Count     : 297
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Mar  2 17:31:39 2016
     13// Update Count     : 226
    1414//
    1515
     
    5454#include "MakeLibCfa.h"
    5555#include "TypeEquality.h"
    56 #include "Autogen.h"
    5756#include "ResolvExpr/typeops.h"
    5857
     
    102101                virtual void visit( StructInstType *structInst );
    103102                virtual void visit( UnionInstType *unionInst );
    104                 virtual void visit( ContextInstType *contextInst );
     103                virtual void visit( TraitInstType *contextInst );
    105104                virtual void visit( StructDecl *structDecl );
    106105                virtual void visit( UnionDecl *unionDecl );
     
    125124
    126125                const Indexer *indexer;
     126        };
     127
     128        class AutogenerateRoutines : public Visitor {
     129          public:
     130                /// Generates assignment operators for aggregate types as required
     131                static void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     132
     133                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
     134
     135                virtual void visit( EnumDecl *enumDecl );
     136                virtual void visit( StructDecl *structDecl );
     137                virtual void visit( UnionDecl *structDecl );
     138                virtual void visit( TypeDecl *typeDecl );
     139                virtual void visit( TraitDecl *ctxDecl );
     140                virtual void visit( FunctionDecl *functionDecl );
     141
     142                virtual void visit( FunctionType *ftype );
     143                virtual void visit( PointerType *ftype );
     144
     145                virtual void visit( CompoundStmt *compoundStmt );
     146                virtual void visit( IfStmt *ifStmt );
     147                virtual void visit( WhileStmt *whileStmt );
     148                virtual void visit( ForStmt *forStmt );
     149                virtual void visit( SwitchStmt *switchStmt );
     150                virtual void visit( ChooseStmt *chooseStmt );
     151                virtual void visit( CaseStmt *caseStmt );
     152                virtual void visit( CatchStmt *catchStmt );
     153
     154                AutogenerateRoutines() : functionNesting( 0 ) {}
     155          private:
     156                template< typename StmtClass > void visitStatement( StmtClass *stmt );
     157
     158                std::list< Declaration * > declsToAdd;
     159                std::set< std::string > structsDone;
     160                unsigned int functionNesting;                   // current level of nested functions
    127161        };
    128162
     
    158192                virtual Declaration *mutate( UnionDecl * unionDecl );
    159193                virtual Declaration *mutate( EnumDecl * enumDecl );
    160                 virtual Declaration *mutate( ContextDecl * contextDecl );
     194                virtual Declaration *mutate( TraitDecl * contextDecl );
    161195
    162196                template<typename AggDecl>
     
    166200                TypedefMap typedefNames;
    167201                int scopeLevel;
    168         };
    169 
    170         class VerifyCtorDtor : public Visitor {
    171         public:
    172                 /// ensure that constructors and destructors have at least one
    173                 /// parameter, the first of which must be a pointer, and no
    174                 /// return values.
    175                 static void verify( std::list< Declaration * > &translationUnit );
    176 
    177                 // VerifyCtorDtor() {}
    178 
    179                 virtual void visit( FunctionDecl *funcDecl );
    180         private:
    181202        };
    182203
     
    190211                acceptAll( translationUnit, pass2 );
    191212                ReturnChecker::checkFunctionReturns( translationUnit );
    192                 autogenerateRoutines( translationUnit );
     213                AutogenerateRoutines::autogenerateRoutines( translationUnit );
    193214                acceptAll( translationUnit, pass3 );
    194                 VerifyCtorDtor::verify( translationUnit );
    195215        }
    196216
     
    202222                type->accept( pass2 );
    203223                type->accept( pass3 );
     224        }
     225
     226        template< typename Visitor >
     227        void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
     228                std::list< Declaration * >::iterator i = translationUnit.begin();
     229                while ( i != translationUnit.end() ) {
     230                        (*i)->accept( visitor );
     231                        std::list< Declaration * >::iterator next = i;
     232                        next++;
     233                        if ( ! visitor.get_declsToAdd().empty() ) {
     234                                translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
     235                        } // if
     236                        i = next;
     237                } // while
    204238        }
    205239
     
    370404        }
    371405
    372         void Pass2::visit( ContextInstType *contextInst ) {
     406        void Pass2::visit( TraitInstType *contextInst ) {
    373407                Parent::visit( contextInst );
    374                 ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() );
     408                TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );
    375409                if ( ! ctx ) {
    376410                        throw SemanticError( "use of undeclared context " + contextInst->get_name() );
     
    378412                for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) {
    379413                        for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
    380                                 if ( ContextInstType *otherCtx = dynamic_cast< ContextInstType * >(*assert ) ) {
     414                                if ( TraitInstType *otherCtx = dynamic_cast< TraitInstType * >(*assert ) ) {
    381415                                        cloneAll( otherCtx->get_members(), contextInst->get_members() );
    382416                                } else {
     
    442476                        while ( ! toBeDone.empty() ) {
    443477                                for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) {
    444                                         if ( ContextInstType *ctx = dynamic_cast< ContextInstType * >( (*assertion )->get_type() ) ) {
     478                                        if ( TraitInstType *ctx = dynamic_cast< TraitInstType * >( (*assertion )->get_type() ) ) {
    445479                                                for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) {
    446480                                                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i );
     
    479513        }
    480514
     515        static const std::list< std::string > noLabels;
     516
     517        void AutogenerateRoutines::autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
     518                AutogenerateRoutines visitor;
     519                acceptAndAdd( translationUnit, visitor, false );
     520        }
     521
     522        template< typename OutputIterator >
     523        void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
     524                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
     525                // unnamed bit fields are not copied as they cannot be accessed
     526                if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
     527
     528                UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
     529
     530                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     531                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     532
     533                // do something special for unnamed members
     534                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
     535                assignExpr->get_args().push_back( dstselect );
     536
     537                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
     538                assignExpr->get_args().push_back( srcselect );
     539
     540                *out++ = new ExprStmt( noLabels, assignExpr );
     541        }
     542
     543        template< typename OutputIterator >
     544        void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
     545                static UniqueName indexName( "_index" );
     546
     547                // for a flexible array member nothing is done -- user must define own assignment
     548                if ( ! array->get_dimension() ) return;
     549
     550                ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
     551                *out++ = new DeclStmt( noLabels, index );
     552
     553                UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     554                init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     555                init->get_args().push_back( new NameExpr( "0" ) );
     556                Statement *initStmt = new ExprStmt( noLabels, init );
     557                std::list<Statement *> initList;
     558                initList.push_back( initStmt );
     559
     560                UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
     561                cond->get_args().push_back( new VariableExpr( index ) );
     562                cond->get_args().push_back( array->get_dimension()->clone() );
     563
     564                UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
     565                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     566
     567                UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
     568
     569                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     570                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     571
     572                Expression *dstselect = new MemberExpr( member, derefExpr );
     573                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
     574                dstIndex->get_args().push_back( dstselect );
     575                dstIndex->get_args().push_back( new VariableExpr( index ) );
     576                assignExpr->get_args().push_back( dstIndex );
     577
     578                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
     579                UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     580                srcIndex->get_args().push_back( srcselect );
     581                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 ) );
     585        }
     586
     587        template< typename OutputIterator >
     588        void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
     589                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
     590                copy->get_args().push_back( new VariableExpr( dstParam ) );
     591                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
     592                copy->get_args().push_back( new SizeofExpr( unionType ) );
     593
     594                *out++ = new ExprStmt( noLabels, copy );
     595        }
     596
     597        //E ?=?(E volatile*, int),
     598        //  ?=?(E _Atomic volatile*, int);
     599        void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
     600                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     601
     602                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
     603                assignType->get_returnVals().push_back( returnVal );
     604
     605                // need two assignment operators with different types
     606                FunctionType * assignType2 = assignType->clone();
     607
     608                // E ?=?(E volatile *, E)
     609                Type *etype = refType->clone();
     610                // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
     611
     612                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
     613                assignType->get_parameters().push_back( dstParam );
     614
     615                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
     616                assignType->get_parameters().push_back( srcParam );
     617
     618                // E ?=?(E volatile *, int)
     619                assignType2->get_parameters().push_back( dstParam->clone() );
     620                BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
     621                ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
     622                assignType2->get_parameters().push_back( srcParam2 );
     623
     624                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     625                // because each unit generates copies of the default routines for each aggregate.
     626
     627                // since there is no definition, these should not be inline
     628                // make these intrinsic so that the code generator does not make use of them
     629                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
     630                assignDecl->fixUniqueId();
     631                FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
     632                assignDecl2->fixUniqueId();
     633
     634                // these should be built in the same way that the prelude
     635                // functions are, so build a list containing the prototypes
     636                // and allow MakeLibCfa to autogenerate the bodies.
     637                std::list< Declaration * > assigns;
     638                assigns.push_back( assignDecl );
     639                assigns.push_back( assignDecl2 );
     640
     641                LibCfa::makeLibCfa( assigns );
     642
     643                // need to remove the prototypes, since this may be nested in a routine
     644                for (int start = 0, end = assigns.size()/2; start < end; start++) {
     645                        delete assigns.front();
     646                        assigns.pop_front();
     647                } // for
     648
     649                declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
     650        }
     651
     652        /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
     653        template< typename GenericInstType >
     654        GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
     655                GenericInstType *clone = refType->clone();
     656                clone->get_parameters().clear();
     657                cloneAll( params, clone->get_parameters() );
     658                return clone;
     659        }
     660
     661        /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
     662        TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
     663                TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
     664
     665                if ( src->get_kind() == TypeDecl::Any ) {
     666                        // just include assignment operator assertion
     667                        TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
     668                        FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
     669                        assignFunctionType->get_returnVals().push_back(
     670                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
     671                        assignFunctionType->get_parameters().push_back(
     672                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
     673                        assignFunctionType->get_parameters().push_back(
     674                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
     675                        FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
     676                        dst->get_assertions().push_back( assignAssert );
     677                }
     678
     679                return dst;
     680        }
     681
     682        Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
     683                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     684
     685                // Make function polymorphic in same parameters as generic struct, if applicable
     686                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
     687                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
     688                std::list< Expression* > structParams;  // List of matching parameters to put on types
     689                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
     690                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
     691                        isGeneric = true;
     692                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     693                        assignType->get_forall().push_back( typeParam );
     694                        TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
     695                        genericSubs.add( (*param)->get_name(), newParamType );
     696                        structParams.push_back( new TypeExpr( newParamType ) );
     697                }
     698
     699                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     700                assignType->get_returnVals().push_back( returnVal );
     701
     702                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
     703                assignType->get_parameters().push_back( dstParam );
     704
     705                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     706                assignType->get_parameters().push_back( srcParam );
     707
     708                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     709                // because each unit generates copies of the default routines for each aggregate.
     710                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
     711                assignDecl->fixUniqueId();
     712
     713                for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
     714                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
     715                                // query the type qualifiers of this field and skip assigning it if it is marked const.
     716                                // If it is an array type, we need to strip off the array layers to find its qualifiers.
     717                                Type * type = dwt->get_type();
     718                                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     719                                        type = at->get_base();
     720                                }
     721
     722                                if ( type->get_qualifiers().isConst ) {
     723                                        // don't assign const members
     724                                        continue;
     725                                }
     726
     727                                if ( isGeneric ) {
     728                                        // rewrite member type in terms of the type variables on this operator
     729                                        DeclarationWithType *fixedMember = dwt->clone();
     730                                        genericSubs.apply( fixedMember );
     731
     732                                        // assign to both destination and return value
     733                                        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() ) );
     736                                        } 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() ) );
     739                                        } // if
     740                                } else {
     741                                        // assign to destination
     742                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
     743                                                makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     744                                        } else {
     745                                                makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     746                                        } // if
     747                                } // if
     748                        } // if
     749                } // for
     750                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     751
     752                return assignDecl;
     753        }
     754
     755        Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
     756                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     757
     758                // Make function polymorphic in same parameters as generic union, if applicable
     759                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
     760                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
     761                std::list< Expression* > unionParams;  // List of matching parameters to put on types
     762                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
     763                        isGeneric = true;
     764                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     765                        assignType->get_forall().push_back( typeParam );
     766                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     767                }
     768
     769                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
     770                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 );
     777
     778                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     779                // because each unit generates copies of the default routines for each aggregate.
     780                FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
     781                assignDecl->fixUniqueId();
     782
     783                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
     784                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
     785               
     786                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     787
     788                return assignDecl;
     789        }
     790
     791        void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
     792                if ( ! enumDecl->get_members().empty() ) {
     793                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
     794                        // enumInst->set_baseEnum( enumDecl );
     795                        // declsToAdd.push_back(
     796                        makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
     797                }
     798        }
     799
     800        void AutogenerateRoutines::visit( StructDecl *structDecl ) {
     801                if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
     802                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
     803                        structInst.set_baseStruct( structDecl );
     804                        declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
     805                        structsDone.insert( structDecl->get_name() );
     806                } // if
     807        }
     808
     809        void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
     810                if ( ! unionDecl->get_members().empty() ) {
     811                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
     812                        unionInst.set_baseUnion( unionDecl );
     813                        declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
     814                } // if
     815        }
     816
     817        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
     818                CompoundStmt *stmts = 0;
     819                TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
     820                typeInst->set_baseType( typeDecl );
     821                ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
     822                ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
     823                if ( typeDecl->get_base() ) {
     824                        stmts = new CompoundStmt( std::list< Label >() );
     825                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
     826                        assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
     827                        assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
     828                        stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
     829                } // if
     830                FunctionType *type = new FunctionType( Type::Qualifiers(), false );
     831                type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
     832                type->get_parameters().push_back( dst );
     833                type->get_parameters().push_back( src );
     834                FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
     835                declsToAdd.push_back( func );
     836        }
     837
     838        void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
     839                for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
     840                        statements.insert( i, new DeclStmt( noLabels, *decl ) );
     841                } // for
     842                declsToAdd.clear();
     843        }
     844
     845        void AutogenerateRoutines::visit( FunctionType *) {
     846                // ensure that we don't add assignment ops for types defined as part of the function
     847        }
     848
     849        void AutogenerateRoutines::visit( PointerType *) {
     850                // ensure that we don't add assignment ops for types defined as part of the pointer
     851        }
     852
     853        void AutogenerateRoutines::visit( TraitDecl *) {
     854                // ensure that we don't add assignment ops for types defined as part of the context
     855        }
     856
     857        template< typename StmtClass >
     858        inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
     859                std::set< std::string > oldStructs = structsDone;
     860                addVisit( stmt, *this );
     861                structsDone = oldStructs;
     862        }
     863
     864        void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
     865                maybeAccept( functionDecl->get_functionType(), *this );
     866                acceptAll( functionDecl->get_oldDecls(), *this );
     867                functionNesting += 1;
     868                maybeAccept( functionDecl->get_statements(), *this );
     869                functionNesting -= 1;
     870        }
     871
     872        void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
     873                visitStatement( compoundStmt );
     874        }
     875
     876        void AutogenerateRoutines::visit( IfStmt *ifStmt ) {
     877                visitStatement( ifStmt );
     878        }
     879
     880        void AutogenerateRoutines::visit( WhileStmt *whileStmt ) {
     881                visitStatement( whileStmt );
     882        }
     883
     884        void AutogenerateRoutines::visit( ForStmt *forStmt ) {
     885                visitStatement( forStmt );
     886        }
     887
     888        void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
     889                visitStatement( switchStmt );
     890        }
     891
     892        void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
     893                visitStatement( switchStmt );
     894        }
     895
     896        void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
     897                visitStatement( caseStmt );
     898        }
     899
     900        void AutogenerateRoutines::visit( CatchStmt *cathStmt ) {
     901                visitStatement( cathStmt );
     902        }
     903
    481904        void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
    482905                ReturnChecker checker;
     
    6521075        }
    6531076
    654                 Declaration *EliminateTypedef::mutate( ContextDecl * contextDecl ) {
     1077                Declaration *EliminateTypedef::mutate( TraitDecl * contextDecl ) {
    6551078                Mutator::mutate( contextDecl );
    6561079                return handleAggregate( contextDecl );
    6571080        }
    6581081
    659         void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
    660                 VerifyCtorDtor verifier;
    661                 acceptAll( translationUnit, verifier );
    662         }
    663 
    664         void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
    665                 FunctionType * funcType = funcDecl->get_functionType();
    666                 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
    667                 std::list< DeclarationWithType * > &params = funcType->get_parameters();
    668 
    669                 if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
    670                         if ( params.size() == 0 ) {
    671                                 throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
    672                         }
    673                         if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
    674                                 throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
    675                         }
    676                         if ( returnVals.size() != 0 ) {
    677                                 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
    678                         }
    679                 }
    680 
    681                 Visitor::visit( funcDecl );
    682                 // original idea: modify signature of ctor/dtors and insert appropriate return statements
    683                 // to cause desired behaviour
    684                 // new idea: add comma exprs to every ctor call to produce first parameter.
    685                 // this requires some memoization of the first parameter, because it can be a
    686                 // complicated expression with side effects (see: malloc). idea: add temporary variable
    687                 // that is assigned address of constructed object in ctor argument position and
    688                 // return the temporary. It should also be done after all implicit ctors are
    689                 // added, so not in this pass!
    690         }
    6911082} // namespace SymTab
    6921083
Note: See TracChangeset for help on using the changeset viewer.