Changeset 83c7e3c


Ignore:
Timestamp:
Dec 23, 2020, 6:37:35 PM (3 years ago)
Author:
caparsons <caparson@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
a3a76ea, c20533ea
Parents:
4c19647 (diff), 09867ec (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r4c19647 r83c7e3c  
    122122        };
    123123
     124        struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
     125                /// hoist dimension from array types in object declaration so that it uses a single
     126                /// const variable of type size_t, so that side effecting array dimensions are only
     127                /// computed once.
     128                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
     129
     130                void premutate( ObjectDecl * objectDecl );
     131                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     132                void premutate( FunctionDecl *functionDecl );
     133                // should not traverse into any of these declarations to find objects
     134                // that need to be constructed or destructed
     135                void premutate( AggregateDecl * ) { visit_children = false; }
     136                void premutate( NamedTypeDecl * ) { visit_children = false; }
     137                void premutate( FunctionType * ) { visit_children = false; }
     138
     139                void hoist( Type * type );
     140
     141                Type::StorageClasses storageClasses;
     142                bool inFunction = false;
     143        };
     144
    124145        void genInit( std::list< Declaration * > & translationUnit ) {
    125                 HoistArrayDimension::hoistArrayDimension( translationUnit );
     146                if (!useNewAST) {
     147                        HoistArrayDimension::hoistArrayDimension( translationUnit );
     148                }
     149                else {
     150                        HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit );
     151                }
    126152                fixReturnStatements( translationUnit );
    127153
     
    196222
    197223                        // need to resolve array dimensions in order to accurately determine if constexpr
    198                         if (!useNewAST) {
    199                                 ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
    200                                 // array is variable-length when the dimension is not constexpr
    201                                 arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
    202                         }
     224                        ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
     225                        // array is variable-length when the dimension is not constexpr
     226                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
    203227                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
    204228                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
     
    218242
    219243        void HoistArrayDimension::premutate( FunctionDecl * ) {
     244                GuardValue( inFunction );
     245                inFunction = true;
     246        }
     247
     248        // precompute array dimension expression, because constructor generation may duplicate it,
     249        // which would be incorrect if it is a side-effecting computation.
     250        void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
     251                PassVisitor<HoistArrayDimension_NoResolve> hoister;
     252                mutateAll( translationUnit, hoister );
     253        }
     254
     255        void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) {
     256                GuardValue( storageClasses );
     257                storageClasses = objectDecl->get_storageClasses();
     258        }
     259
     260        DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) {
     261                hoist( objectDecl->get_type() );
     262                return objectDecl;
     263        }
     264
     265        void HoistArrayDimension_NoResolve::hoist( Type * type ) {
     266                // if in function, generate const size_t var
     267                static UniqueName dimensionName( "_array_dim" );
     268
     269                // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
     270                if ( ! inFunction ) return;
     271                if ( storageClasses.is_static ) return;
     272
     273                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     274                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
     275                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
     276                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
     277                        // still try to detect constant expressions
     278                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
     279
     280                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     281                        arrayDimension->get_type()->set_const( true );
     282
     283                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
     284                        declsToAddBefore.push_back( arrayDimension );
     285
     286                        hoist( arrayType->get_base() );
     287                        return;
     288                }
     289        }
     290
     291        void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) {
    220292                GuardValue( inFunction );
    221293                inFunction = true;
  • src/ResolvExpr/CandidateFinder.cpp

    r4c19647 r83c7e3c  
    905905                        // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?
    906906                        // this means there exists ctor/assign functions with a tuple as first parameter.
    907                         funcFinder.find( untypedExpr->func, selfFinder.candidates.empty() ? ResolvMode::withAdjustment() : ResolvMode::withoutFailFast() );
     907                        ResolvMode mode = {
     908                                true, // adjust
     909                                !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name
     910                                selfFinder.candidates.empty() // failfast if other options are not found
     911                        };
     912                        funcFinder.find( untypedExpr->func, mode );
    908913                        // short-circuit if no candidates
    909914                        // if ( funcFinder.candidates.empty() ) return;
  • src/ResolvExpr/ResolvMode.h

    r4c19647 r83c7e3c  
    2323                const bool failFast;         ///< Fail on no resulting alternatives? [true]
    2424
    25         private:
    2625                constexpr ResolvMode(bool a, bool p, bool ff)
    2726                : adjust(a), prune(p), failFast(ff) {}
    2827
    29         public:
    3028                /// Default settings
    3129                constexpr ResolvMode() : adjust(false), prune(true), failFast(true) {}
  • src/SymTab/Validate.cc

    r4c19647 r83c7e3c  
    271271        };
    272272
    273         struct ArrayLength : public WithIndexer {
     273        struct InitializerLength {
    274274                /// for array types without an explicit length, compute the length and store it so that it
    275275                /// is known to the rest of the phases. For example,
     
    282282
    283283                void previsit( ObjectDecl * objDecl );
     284        };
     285
     286        struct ArrayLength : public WithIndexer {
     287                static void computeLength( std::list< Declaration * > & translationUnit );
     288
    284289                void previsit( ArrayType * arrayType );
    285290        };
     
    382387                                        FixObjectType::fix, translationUnit);
    383388                        }
    384                         Stats::Time::TimeCall("Array Length",
    385                                 ArrayLength::computeLength, translationUnit);
     389                        Stats::Time::TimeCall("Initializer Length",
     390                                InitializerLength::computeLength, translationUnit);
     391                        if (!useNewAST) {
     392                                Stats::Time::TimeCall("Array Length",
     393                                        ArrayLength::computeLength, translationUnit);
     394                        }
    386395                        Stats::Time::TimeCall("Find Special Declarations",
    387396                                Validate::findSpecialDecls, translationUnit);
     
    13321341        }
    13331342
     1343        void InitializerLength::computeLength( std::list< Declaration * > & translationUnit ) {
     1344                PassVisitor<InitializerLength> len;
     1345                acceptAll( translationUnit, len );
     1346        }
     1347
    13341348        void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
    13351349                PassVisitor<ArrayLength> len;
     
    13371351        }
    13381352
    1339         void ArrayLength::previsit( ObjectDecl * objDecl ) {
     1353        void InitializerLength::previsit( ObjectDecl * objDecl ) {
    13401354                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) {
    13411355                        if ( at->dimension ) return;
     
    13471361
    13481362        void ArrayLength::previsit( ArrayType * type ) {
    1349                 if (!useNewAST) {
    1350                         if ( type->dimension ) {
    1351                                 // need to resolve array dimensions early so that constructor code can correctly determine
    1352                                 // if a type is a VLA (and hence whether its elements need to be constructed)
    1353                                 ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    1354 
    1355                                 // must re-evaluate whether a type is a VLA, now that more information is available
    1356                                 // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
    1357                                 type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
    1358                         }
     1363                if ( type->dimension ) {
     1364                        // need to resolve array dimensions early so that constructor code can correctly determine
     1365                        // if a type is a VLA (and hence whether its elements need to be constructed)
     1366                        ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     1367
     1368                        // must re-evaluate whether a type is a VLA, now that more information is available
     1369                        // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
     1370                        type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
    13591371                }
    13601372        }
Note: See TracChangeset for help on using the changeset viewer.