Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    re3e16bc re35f30a  
    2626#include "Common/UniqueName.h"     // for UniqueName
    2727#include "Common/utility.h"        // for ValueGuard, maybeClone
    28 #include "GenPoly/DeclMutator.h"   // for DeclMutator
    2928#include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
    3029#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
     
    6261        };
    6362
    64         struct CtorDtor : public WithGuards, public WithShortCircuiting  {
     63        struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
    6564                /// create constructor and destructor statements for object declarations.
    6665                /// the actual call statements will be added in after the resolver has run
     
    7574                // that need to be constructed or destructed
    7675                void previsit( StructDecl *aggregateDecl );
    77                 void previsit( __attribute__((unused)) UnionDecl    * aggregateDecl ) { visit_children = false; }
    78                 void previsit( __attribute__((unused)) EnumDecl     * aggregateDecl ) { visit_children = false; }
    79                 void previsit( __attribute__((unused)) TraitDecl    * aggregateDecl ) { visit_children = false; }
    80                 void previsit( __attribute__((unused)) TypeDecl     * typeDecl )      { visit_children = false; }
    81                 void previsit( __attribute__((unused)) TypedefDecl  * typeDecl )      { visit_children = false; }
    82                 void previsit( __attribute__((unused)) FunctionType * funcType )      { visit_children = false; }
     76                void previsit( AggregateDecl * ) { visit_children = false; }
     77                void previsit( NamedTypeDecl * ) { visit_children = false; }
     78                void previsit( FunctionType * ) { visit_children = false; }
    8379
    8480                void previsit( CompoundStmt * compoundStmt );
     
    8985                // should not have a ConstructorInit generated.
    9086
    91                 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
    92                 bool isManaged( Type * type ) const; // determine if type is managed
    93                 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    94                 GenPoly::ScopedSet< std::string > managedTypes;
     87                ManagedTypes managedTypes;
    9588                bool inFunction = false;
    9689        };
    9790
    98         class HoistArrayDimension final : public GenPoly::DeclMutator {
    99           public:
    100                 typedef GenPoly::DeclMutator Parent;
    101 
     91        struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
    10292                /// hoist dimension from array types in object declaration so that it uses a single
    10393                /// const variable of type size_t, so that side effecting array dimensions are only
     
    10595                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    10696
    107           private:
    108                 using Parent::mutate;
    109 
    110                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
    111                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     97                void premutate( ObjectDecl * objectDecl );
     98                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     99                void premutate( FunctionDecl *functionDecl );
    112100                // should not traverse into any of these declarations to find objects
    113101                // that need to be constructed or destructed
    114                 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; }
    115                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
    116                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
    117                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
    118                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
    119                 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
    120 
    121                 virtual Type* mutate( FunctionType *funcType ) override { return funcType; }
     102                void premutate( AggregateDecl * ) { visit_children = false; }
     103                void premutate( NamedTypeDecl * ) { visit_children = false; }
     104                void premutate( FunctionType * ) { visit_children = false; }
    122105
    123106                void hoist( Type * type );
     
    128111
    129112        void genInit( std::list< Declaration * > & translationUnit ) {
    130                 ReturnFixer::makeReturnTemp( translationUnit );
     113                fixReturnStatements( translationUnit );
    131114                HoistArrayDimension::hoistArrayDimension( translationUnit );
    132115                CtorDtor::generateCtorDtor( translationUnit );
    133116        }
    134117
    135         void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
     118        void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
    136119                PassVisitor<ReturnFixer> fixer;
    137120                mutateAll( translationUnit, fixer );
     
    143126                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    144127                // is being returned
    145                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
     128                if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    146129                        // explicitly construct the return value using the return expression and the retVal object
    147                         assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    148 
    149                         stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
     130                        assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
     131
     132                        ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
     133                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) {
     134                                // return statement has already been mutated - don't need to do it again
     135                                if ( varExpr->var == retVal ) return;
     136                        }
     137                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) );
    150138
    151139                        // return the retVal object
    152                         returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
     140                        returnStmt->expr = new VariableExpr( returnVals.front() );
    153141                } // if
    154142        }
     
    158146                GuardValue( funcName );
    159147
    160                 ftype = functionDecl->get_functionType();
    161                 funcName = functionDecl->get_name();
     148                ftype = functionDecl->type;
     149                funcName = functionDecl->name;
    162150        }
    163151
     
    165153        // which would be incorrect if it is a side-effecting computation.
    166154        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    167                 HoistArrayDimension hoister;
    168                 hoister.mutateDeclarationList( translationUnit );
    169         }
    170 
    171         DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     155                PassVisitor<HoistArrayDimension> hoister;
     156                mutateAll( translationUnit, hoister );
     157        }
     158
     159        void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
     160                GuardValue( storageClasses );
    172161                storageClasses = objectDecl->get_storageClasses();
    173                 DeclarationWithType * temp = Parent::mutate( objectDecl );
     162        }
     163
     164        DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
    174165                hoist( objectDecl->get_type() );
    175                 return temp;
     166                return objectDecl;
    176167        }
    177168
     
    194185
    195186                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    196                         addDeclaration( arrayDimension );
     187                        declsToAddBefore.push_back( arrayDimension );
    197188
    198189                        hoist( arrayType->get_base() );
     
    201192        }
    202193
    203         DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    204                 ValueGuard< bool > oldInFunc( inFunction );
    205                 inFunction = true;
    206                 DeclarationWithType * decl = Parent::mutate( functionDecl );
    207                 return decl;
     194        void HoistArrayDimension::premutate( FunctionDecl * ) {
     195                GuardValue( inFunction );
    208196        }
    209197
     
    213201        }
    214202
    215         bool CtorDtor::isManaged( Type * type ) const {
    216                 // at least for now, references are never constructed
     203        bool ManagedTypes::isManaged( Type * type ) const {
     204                // references are never constructed
    217205                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    218206                // need to clear and reset qualifiers when determining if a type is managed
     
    221209                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    222210                        // tuple is also managed if any of its components are managed
    223                         if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
     211                        if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
    224212                                return true;
    225213                        }
    226214                }
    227215                // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
    228                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
    229         }
    230 
    231         bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
     216                return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
     217        }
     218
     219        bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const {
    232220                Type * type = objDecl->get_type();
    233221                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     
    237225        }
    238226
    239         void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
     227        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    240228                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    241229                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
     
    244232                        Type * type = InitTweak::getPointerBase( params.front()->get_type() );
    245233                        assert( type );
    246                         managedTypes.insert( SymTab::Mangler::mangle( type ) );
    247                 }
    248         }
     234                        managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) );
     235                }
     236        }
     237
     238        void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) {
     239                // don't construct members, but need to take note if there is a managed member,
     240                // because that means that this type is also managed
     241                for ( Declaration * member : aggregateDecl->get_members() ) {
     242                        if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     243                                if ( isManaged( field ) ) {
     244                                        // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
     245                                        // polymorphic constructors make generic types managed types
     246                                        StructInstType inst( Type::Qualifiers(), aggregateDecl );
     247                                        managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) );
     248                                        break;
     249                                }
     250                        }
     251                }
     252        }
     253
     254        void ManagedTypes::beginScope() { managedTypes.beginScope(); }
     255        void ManagedTypes::endScope() { managedTypes.endScope(); }
    249256
    250257        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
     
    291298
    292299        void CtorDtor::previsit( ObjectDecl * objDecl ) {
    293                 handleDWT( objDecl );
     300                managedTypes.handleDWT( objDecl );
    294301                // hands off if @=, extern, builtin, etc.
    295302                // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C
    296                 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
     303                if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    297304                        // constructed objects cannot be designated
    298305                        if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
     
    305312
    306313        void CtorDtor::previsit( FunctionDecl *functionDecl ) {
     314                visit_children = false;  // do not try and construct parameters or forall parameters
    307315                GuardValue( inFunction );
    308316                inFunction = true;
    309317
    310                 handleDWT( functionDecl );
     318                managedTypes.handleDWT( functionDecl );
    311319
    312320                GuardScope( managedTypes );
     
    314322                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    315323                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    316                                 handleDWT( assertion );
     324                                managedTypes.handleDWT( assertion );
    317325                        }
    318326                }
    319327
    320                 PassVisitor<CtorDtor> newCtorDtor;
    321                 newCtorDtor.pass = *this;
    322                 maybeAccept( functionDecl->get_statements(), newCtorDtor );
    323                 visit_children = false;  // do not try and construct parameters or forall parameters - must happen after maybeAccept
     328                maybeAccept( functionDecl->get_statements(), *visitor );
    324329        }
    325330
     
    327332                visit_children = false; // do not try to construct and destruct aggregate members
    328333
    329                 // don't construct members, but need to take note if there is a managed member,
    330                 // because that means that this type is also managed
    331                 for ( Declaration * member : aggregateDecl->get_members() ) {
    332                         if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
    333                                 if ( isManaged( field ) ) {
    334                                         StructInstType inst( Type::Qualifiers(), aggregateDecl );
    335                                         managedTypes.insert( SymTab::Mangler::mangle( &inst ) );
    336                                         break;
    337                                 }
    338                         }
    339                 }
    340         }
    341 
    342         void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) {
     334                managedTypes.handleStruct( aggregateDecl );
     335        }
     336
     337        void CtorDtor::previsit( CompoundStmt * ) {
    343338                GuardScope( managedTypes );
    344339        }
Note: See TracChangeset for help on using the changeset viewer.