Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r62e5546 rf0121d7  
    2929#include "GenPoly/DeclMutator.h"
    3030#include "GenPoly/ScopedSet.h"
     31#include "ResolvExpr/typeops.h"
    3132
    3233namespace InitTweak {
     
    3637        }
    3738
    38         class ReturnFixer final : public GenPoly::PolyMutator {
     39        class ReturnFixer : public GenPoly::PolyMutator {
    3940          public:
    4041                /// consistently allocates a temporary variable for the return value
     
    4546                ReturnFixer();
    4647
    47                 using GenPoly::PolyMutator::mutate;
    48                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
    49                 virtual Statement * mutate( ReturnStmt * returnStmt ) override;
     48                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
     49
     50                virtual Statement * mutate( ReturnStmt * returnStmt );
    5051
    5152          protected:
    52                 std::list<DeclarationWithType*> returnVals;
     53                FunctionType * ftype;
    5354                UniqueName tempNamer;
    5455                std::string funcName;
    5556        };
    5657
    57         class CtorDtor final : public GenPoly::PolyMutator {
     58        class CtorDtor : public GenPoly::PolyMutator {
    5859          public:
    5960                typedef GenPoly::PolyMutator Parent;
     
    6566                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    6667
    67                 virtual DeclarationWithType * mutate( ObjectDecl * ) override;
    68                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     68                virtual DeclarationWithType * mutate( ObjectDecl * );
     69                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    6970                // should not traverse into any of these declarations to find objects
    7071                // that need to be constructed or destructed
    71                 virtual Declaration* mutate( StructDecl *aggregateDecl ) override;
    72                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
    73                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
    74                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
    75                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
    76                 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
    77 
    78                 virtual Type * mutate( FunctionType *funcType ) override { return funcType; }
    79 
    80                 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override;
     72                virtual Declaration* mutate( StructDecl *aggregateDecl );
     73                virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
     74                virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     75                virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
     76                virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
     77                virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
     78
     79                virtual Type * mutate( FunctionType *funcType ) { return funcType; }
     80
     81                virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
    8182
    8283          private:
     
    8687
    8788                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
     89                bool isManaged( Type * type ) const; // determine if type is managed
    8890                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    8991                GenPoly::ScopedSet< std::string > managedTypes;
     
    9193        };
    9294
    93         class HoistArrayDimension final : public GenPoly::DeclMutator {
     95        class HoistArrayDimension : public GenPoly::DeclMutator {
    9496          public:
    9597                typedef GenPoly::DeclMutator Parent;
     
    101103
    102104          private:
    103                 using Parent::mutate;
    104 
    105                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
    106                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     105                virtual DeclarationWithType * mutate( ObjectDecl * objectDecl );
     106                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    107107                // should not traverse into any of these declarations to find objects
    108108                // that need to be constructed or destructed
    109                 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; }
    110                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
    111                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
    112                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
    113                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
    114                 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
    115 
    116                 virtual Type* mutate( FunctionType *funcType ) override { return funcType; }
     109                virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
     110                virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
     111                virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     112                virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
     113                virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
     114                virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
     115
     116                virtual Type* mutate( FunctionType *funcType ) { return funcType; }
    117117
    118118                void hoist( Type * type );
     
    136136
    137137        Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
    138                 // update for multiple return values
     138                std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    139139                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    140140                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     
    158158
    159159        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    160                 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
     160                // xxx - need to handle named return values - this pass may need to happen
     161                // after resolution? the ordering is tricky because return statements must be
     162                // constructed - the simplest way to do that (while also handling multiple
     163                // returns) is to structure the returnVals into a tuple, as done here.
     164                // however, if the tuple return value is structured before resolution,
     165                // it's difficult to resolve named return values, since the name is lost
     166                // in conversion to a tuple. this might be easiest to deal with
     167                // after reference types are added, as it may then be possible to
     168                // uniformly move named return values to the parameter list directly
     169                ValueGuard< FunctionType * > oldFtype( ftype );
    161170                ValueGuard< std::string > oldFuncName( funcName );
    162171
    163                 FunctionType * type = functionDecl->get_functionType();
    164                 returnVals = type->get_returnVals();
     172                ftype = functionDecl->get_functionType();
     173                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     174                if ( retVals.size() > 1 ) {
     175                        TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
     176                        ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
     177                        retVals.clear();
     178                        retVals.push_back( newRet );
     179                }
    165180                funcName = functionDecl->get_name();
    166181                DeclarationWithType * decl = Mutator::mutate( functionDecl );
     
    222237        }
    223238
     239        bool CtorDtor::isManaged( Type * type ) const {
     240                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
     241                        // tuple is also managed if any of its components are managed
     242                        if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
     243                                return true;
     244                        }
     245                }
     246                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     247        }
     248
    224249        bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
    225250                Type * type = objDecl->get_type();
     
    227252                        type = at->get_base();
    228253                }
    229                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     254                return isManaged( type );
    230255        }
    231256
     
    238263                        managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
    239264                }
     265        }
     266
     267        ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
     268                // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     269                // for each constructable object
     270                std::list< Statement * > ctor;
     271                std::list< Statement * > dtor;
     272
     273                InitExpander srcParam( objDecl->get_init() );
     274                InitExpander nullParam( (Initializer *)NULL );
     275                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     276                SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     277
     278                // Currently genImplicitCall produces a single Statement - a CompoundStmt
     279                // which  wraps everything that needs to happen. As such, it's technically
     280                // possible to use a Statement ** in the above calls, but this is inherently
     281                // unsafe, so instead we take the slightly less efficient route, but will be
     282                // immediately informed if somehow the above assumption is broken. In this case,
     283                // we could always wrap the list of statements at this point with a CompoundStmt,
     284                // but it seems reasonable at the moment for this to be done by genImplicitCall
     285                // itself. It is possible that genImplicitCall produces no statements (e.g. if
     286                // an array type does not have a dimension). In this case, it's fine to ignore
     287                // the object for the purposes of construction.
     288                assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     289                if ( ctor.size() == 1 ) {
     290                        // need to remember init expression, in case no ctors exist
     291                        // if ctor does exist, want to use ctor expression instead of init
     292                        // push this decision to the resolver
     293                        assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     294                        return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
     295                }
     296                return nullptr;
    240297        }
    241298
     
    250307                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
    251308
    252                         // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    253                         // for each constructable object
    254                         std::list< Statement * > ctor;
    255                         std::list< Statement * > dtor;
    256 
    257                         InitExpander srcParam( objDecl->get_init() );
    258                         InitExpander nullParam( (Initializer *)NULL );
    259                         SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    260                         SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    261 
    262                         // Currently genImplicitCall produces a single Statement - a CompoundStmt
    263                         // which  wraps everything that needs to happen. As such, it's technically
    264                         // possible to use a Statement ** in the above calls, but this is inherently
    265                         // unsafe, so instead we take the slightly less efficient route, but will be
    266                         // immediately informed if somehow the above assumption is broken. In this case,
    267                         // we could always wrap the list of statements at this point with a CompoundStmt,
    268                         // but it seems reasonable at the moment for this to be done by genImplicitCall
    269                         // itself. It is possible that genImplicitCall produces no statements (e.g. if
    270                         // an array type does not have a dimension). In this case, it's fine to ignore
    271                         // the object for the purposes of construction.
    272                         assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    273                         if ( ctor.size() == 1 ) {
    274                                 // need to remember init expression, in case no ctors exist
    275                                 // if ctor does exist, want to use ctor expression instead of init
    276                                 // push this decision to the resolver
    277                                 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    278                                 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    279                         }
     309                        objDecl->set_init( genCtorInit( objDecl ) );
    280310                }
    281311                return Parent::mutate( objDecl );
     
    290320                managedTypes.beginScope();
    291321                // go through assertions and recursively add seen ctor/dtors
    292                 for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
     322                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    293323                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    294324                                assertion = assertion->acceptMutator( *this );
Note: See TracChangeset for help on using the changeset viewer.