Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    ra139c11 r4e8949f  
    1616#include "Autogen.h"
    1717
     18#include <cstddef>                 // for NULL
    1819#include <algorithm>               // for count_if
    1920#include <cassert>                 // for strict_dynamic_cast, assert, assertf
     
    2627#include "AddVisit.h"              // for addVisit
    2728#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    28 #include "Common/PassVisitor.h"    // for PassVisitor
    2929#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
    3030#include "Common/utility.h"        // for cloneAll, operator+
     31#include "GenPoly/DeclMutator.h"   // for DeclMutator
    3132#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
    32 #include "InitTweak/GenInit.h"     // for fixReturnStatements
    33 #include "ResolvExpr/Resolver.h"   // for resolveDecl
    3433#include "SymTab/Mangler.h"        // for Mangler
    3534#include "SynTree/Attribute.h"     // For Attribute
     
    5453        };
    5554
    56         struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting {
     55        class AutogenerateRoutines final : public Visitor {
     56            template< typename Visitor >
     57            friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
     58            template< typename Visitor >
     59            friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
     60          public:
     61                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
     62
     63                typedef Visitor Parent;
     64                using Parent::visit;
     65
    5766                AutogenerateRoutines();
    5867
    59                 void previsit( EnumDecl * enumDecl );
    60                 void previsit( StructDecl * structDecl );
    61                 void previsit( UnionDecl * structDecl );
    62                 void previsit( TypeDecl * typeDecl );
    63                 void previsit( TraitDecl * traitDecl );
    64                 void previsit( FunctionDecl * functionDecl );
    65 
    66                 void previsit( FunctionType * ftype );
    67                 void previsit( PointerType * ptype );
    68 
    69                 void previsit( CompoundStmt * compoundStmt );
     68                virtual void visit( EnumDecl *enumDecl );
     69                virtual void visit( StructDecl *structDecl );
     70                virtual void visit( UnionDecl *structDecl );
     71                virtual void visit( TypeDecl *typeDecl );
     72                virtual void visit( TraitDecl *ctxDecl );
     73                virtual void visit( FunctionDecl *functionDecl );
     74
     75                virtual void visit( FunctionType *ftype );
     76                virtual void visit( PointerType *ftype );
     77
     78                virtual void visit( CompoundStmt *compoundStmt );
     79                virtual void visit( SwitchStmt *switchStmt );
    7080
    7181          private:
    72                 GenPoly::ScopedSet< std::string > structsDone;
     82                template< typename StmtClass > void visitStatement( StmtClass *stmt );
     83
     84                std::list< Declaration * > declsToAdd, declsToAddAfter;
     85                std::set< std::string > structsDone;
    7386                unsigned int functionNesting = 0;     // current level of nested functions
    7487                /// Note: the following maps could be ScopedSets, but it should be easier to work
     
    8093
    8194        /// generates routines for tuple types.
    82         struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting {
    83                 void previsit( FunctionDecl *functionDecl );
    84 
    85                 void postvisit( TupleType *tupleType );
    86 
    87                 void previsit( CompoundStmt *compoundStmt );
     95        /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit
     96        /// or anything we currently have that supports adding new declarations for visitors
     97        class AutogenTupleRoutines : public GenPoly::DeclMutator {
     98          public:
     99                typedef GenPoly::DeclMutator Parent;
     100                using Parent::mutate;
     101
     102                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
     103
     104                virtual Type * mutate( TupleType *tupleType );
     105
     106                virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );
    88107
    89108          private:
     
    93112
    94113        void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    95                 PassVisitor<AutogenerateRoutines> generator;
    96                 acceptAll( translationUnit, generator );
     114                AutogenerateRoutines generator;
     115                acceptAndAdd( translationUnit, generator );
    97116
    98117                // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
    99118                // AutogenTupleRoutines tupleGenerator;
    100                 // acceptAll( translationUnit, tupleGenerator );
     119                // tupleGenerator.mutateDeclarationList( translationUnit );
    101120        }
    102121
    103122        bool isUnnamedBitfield( ObjectDecl * obj ) {
    104                 return obj != nullptr && obj->get_name() == "" && obj->get_bitfieldWidth() != nullptr;
     123                return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
    105124        }
    106125
     
    109128                FunctionDecl * decl = functionDecl->clone();
    110129                delete decl->get_statements();
    111                 decl->set_statements( nullptr );
     130                decl->set_statements( NULL );
    112131                declsToAdd.push_back( decl );
    113132                decl->fixUniqueId();
     
    320339                                assert( ! func->get_functionType()->get_parameters().empty() );
    321340                                ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
    322                                 ObjectDecl * srcParam = nullptr;
     341                                ObjectDecl * srcParam = NULL;
    323342                                if ( func->get_functionType()->get_parameters().size() == 2 ) {
    324343                                        srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
     
    327346                                assert( dstParam );
    328347
    329                                 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr;
     348                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    330349                                makeStructMemberOp( dstParam, srcselect, field, func, forward );
    331350                        } // if
     
    366385                                } else {
    367386                                        // no matching parameter, initialize field with default ctor
    368                                         makeStructMemberOp( dstParam, nullptr, field, func );
     387                                        makeStructMemberOp( dstParam, NULL, field, func );
    369388                                }
    370389                        }
     
    382401        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
    383402                // Builtins do not use autogeneration.
    384                 if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) {
     403                if ( aggregateDecl->get_linkage() == LinkageSpec::BuiltinCFA ||
     404                         aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) {
    385405                        return;
    386406                }
    387407
    388408                // Make function polymorphic in same parameters as generic struct, if applicable
    389                 const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     409                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    390410
    391411                // generate each of the functions based on the supplied FuncData objects
     
    552572                // the order here determines the order that these functions are generated.
    553573                // assignment should come last since it uses copy constructor in return.
    554                 data.emplace_back( "?{}", genDefaultType, constructable );
    555                 data.emplace_back( "?{}", genCopyType, copyable );
    556                 data.emplace_back( "^?{}", genDefaultType, destructable );
    557                 data.emplace_back( "?=?", genAssignType, assignable );
    558         }
    559 
    560         void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) {
    561                 visit_children = false;
     574                data.push_back( FuncData( "?{}", genDefaultType, constructable ) );
     575                data.push_back( FuncData( "?{}", genCopyType, copyable ) );
     576                data.push_back( FuncData( "^?{}", genDefaultType, destructable ) );
     577                data.push_back( FuncData( "?=?", genAssignType, assignable ) );
     578        }
     579
     580        void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
    562581                if ( ! enumDecl->get_members().empty() ) {
    563582                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
     
    567586        }
    568587
    569         void AutogenerateRoutines::previsit( StructDecl * structDecl ) {
    570                 visit_children = false;
    571                 if ( structDecl->has_body() && structsDone.find( structDecl->name ) == structsDone.end() ) {
    572                         StructInstType structInst( Type::Qualifiers(), structDecl->name );
    573                         for ( TypeDecl * typeDecl : structDecl->parameters ) {
     588        void AutogenerateRoutines::visit( StructDecl *structDecl ) {
     589                if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
     590                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
     591                        for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
    574592                                // need to visit assertions so that they are added to the appropriate maps
    575                                 acceptAll( typeDecl->assertions, *visitor );
    576                                 structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) );
     593                                acceptAll( typeDecl->get_assertions(), *this );
     594                                structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    577595                        }
    578596                        structInst.set_baseStruct( structDecl );
    579597                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );
    580                         structsDone.insert( structDecl->name );
     598                        structsDone.insert( structDecl->get_name() );
    581599                } // if
    582600        }
    583601
    584         void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) {
    585                 visit_children = false;
     602        void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
    586603                if ( ! unionDecl->get_members().empty() ) {
    587604                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
     
    602619
    603620        // generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
    604         void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) {
    605                 visit_children = false;
     621        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
    606622                if ( ! typeDecl->base ) return;
    607623
     
    648664        }
    649665
    650         void AutogenerateRoutines::previsit( FunctionType *) {
     666        void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
     667                for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
     668                        statements.insert( i, new DeclStmt( noLabels, *decl ) );
     669                } // for
     670                declsToAdd.clear();
     671        }
     672
     673        void AutogenerateRoutines::visit( FunctionType *) {
    651674                // ensure that we don't add assignment ops for types defined as part of the function
    652                 visit_children = false;
    653         }
    654 
    655         void AutogenerateRoutines::previsit( PointerType *) {
     675        }
     676
     677        void AutogenerateRoutines::visit( PointerType *) {
    656678                // ensure that we don't add assignment ops for types defined as part of the pointer
    657                 visit_children = false;
    658         }
    659 
    660         void AutogenerateRoutines::previsit( TraitDecl * ) {
     679        }
     680
     681        void AutogenerateRoutines::visit( TraitDecl *) {
    661682                // ensure that we don't add assignment ops for types defined as part of the trait
    662                 visit_children = false;
    663         }
    664 
    665         void AutogenerateRoutines::previsit( FunctionDecl * functionDecl ) {
    666                 visit_children = false;
     683        }
     684
     685        template< typename StmtClass >
     686        inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
     687                std::set< std::string > oldStructs = structsDone;
     688                addVisit( stmt, *this );
     689                structsDone = oldStructs;
     690        }
     691
     692        void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
    667693                // record the existence of this function as appropriate
    668694                insert( functionDecl, constructable, InitTweak::isDefaultConstructor );
     
    671697                insert( functionDecl, destructable, InitTweak::isDestructor );
    672698
    673                 maybeAccept( functionDecl->type, *visitor );
     699                maybeAccept( functionDecl->get_functionType(), *this );
    674700                functionNesting += 1;
    675                 maybeAccept( functionDecl->statements, *visitor );
     701                maybeAccept( functionDecl->get_statements(), *this );
    676702                functionNesting -= 1;
    677703        }
    678704
    679         void AutogenerateRoutines::previsit( CompoundStmt * ) {
    680                 GuardScope( constructable );
    681                 GuardScope( assignable );
    682                 GuardScope( copyable );
    683                 GuardScope( destructable );
    684                 GuardScope( structsDone );
     705        void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
     706                constructable.beginScope();
     707                assignable.beginScope();
     708                copyable.beginScope();
     709                destructable.beginScope();
     710                visitStatement( compoundStmt );
     711                constructable.endScope();
     712                assignable.endScope();
     713                copyable.endScope();
     714                destructable.endScope();
     715        }
     716
     717        void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
     718                visitStatement( switchStmt );
    685719        }
    686720
     
    700734        }
    701735
    702         void AutogenTupleRoutines::postvisit( TupleType * tupleType ) {
     736        Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
     737                tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
    703738                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
    704                 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return;
     739                if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
    705740                seenTuples.insert( mangleName );
    706741
     
    750785                makeTupleFunctionBody( dtorDecl );
    751786
    752                 declsToAddBefore.push_back( ctorDecl );
    753                 declsToAddBefore.push_back( copyCtorDecl );
    754                 declsToAddBefore.push_back( dtorDecl );
    755                 declsToAddBefore.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    756         }
    757 
    758         void AutogenTupleRoutines::previsit( FunctionDecl *functionDecl ) {
    759                 visit_children = false;
    760                 maybeAccept( functionDecl->type, *visitor );
     787                addDeclaration( ctorDecl );
     788                addDeclaration( copyCtorDecl );
     789                addDeclaration( dtorDecl );
     790                addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return
     791
     792                return tupleType;
     793        }
     794
     795        DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {
     796                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
    761797                functionNesting += 1;
    762                 maybeAccept( functionDecl->statements, *visitor );
     798                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    763799                functionNesting -= 1;
    764         }
    765 
    766         void AutogenTupleRoutines::previsit( CompoundStmt * ) {
    767                 GuardScope( seenTuples );
     800                return functionDecl;
     801        }
     802
     803        CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
     804                seenTuples.beginScope();
     805                compoundStmt = strict_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
     806                seenTuples.endScope();
     807                return compoundStmt;
    768808        }
    769809} // SymTab
Note: See TracChangeset for help on using the changeset viewer.