Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    rcad355a rf9cebb5  
     1#include <algorithm>
    12#include "InitTweak.h"
    23#include "SynTree/Visitor.h"
     
    45#include "SynTree/Initializer.h"
    56#include "SynTree/Expression.h"
     7#include "SynTree/Attribute.h"
    68#include "GenPoly/GenPoly.h"
    79
     
    2022                };
    2123
    22                 class InitExpander : public Visitor {
     24                class InitFlattener : public Visitor {
    2325                        public:
    24                         InitExpander() {}
    2526                        virtual void visit( SingleInit * singleInit );
    2627                        virtual void visit( ListInit * listInit );
     
    2829                };
    2930
    30                 void InitExpander::visit( SingleInit * singleInit ) {
     31                void InitFlattener::visit( SingleInit * singleInit ) {
    3132                        argList.push_back( singleInit->get_value()->clone() );
    3233                }
    3334
    34                 void InitExpander::visit( ListInit * listInit ) {
    35                         // xxx - for now, assume no nested list inits
    36                         std::list<Initializer*>::iterator it = listInit->begin_initializers();
    37                         for ( ; it != listInit->end_initializers(); ++it ) {
     35                void InitFlattener::visit( ListInit * listInit ) {
     36                        // flatten nested list inits
     37                        std::list<Initializer*>::iterator it = listInit->begin();
     38                        for ( ; it != listInit->end(); ++it ) {
    3839                                (*it)->accept( *this );
    3940                        }
     
    4243
    4344        std::list< Expression * > makeInitList( Initializer * init ) {
    44                 InitExpander expander;
    45                 maybeAccept( init, expander );
    46                 return expander.argList;
     45                InitFlattener flattener;
     46                maybeAccept( init, flattener );
     47                return flattener.argList;
    4748        }
    4849
     
    5354        }
    5455
     56        class InitExpander::ExpanderImpl {
     57        public:
     58                virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
     59                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
     60        };
     61
     62        class InitImpl : public InitExpander::ExpanderImpl {
     63        public:
     64                InitImpl( Initializer * init ) : init( init ) {}
     65
     66                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     67                        // this is wrong, but just a placeholder for now
     68                        // if ( ! flattened ) flatten( indices );
     69                        // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
     70                        return makeInitList( init );
     71                }
     72
     73                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
     74        private:
     75                Initializer * init;
     76        };
     77
     78        class ExprImpl : public InitExpander::ExpanderImpl {
     79        public:
     80                ExprImpl( Expression * expr ) : arg( expr ) {}
     81
     82                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     83                        std::list< Expression * > ret;
     84                        Expression * expr = maybeClone( arg );
     85                        if ( expr ) {
     86                                for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
     87                                        // go through indices and layer on subscript exprs ?[?]
     88                                        ++it;
     89                                        UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
     90                                        subscriptExpr->get_args().push_back( expr );
     91                                        subscriptExpr->get_args().push_back( (*it)->clone() );
     92                                        expr = subscriptExpr;
     93                                }
     94                                ret.push_back( expr );
     95                        }
     96                        return ret;
     97                }
     98
     99                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
     100        private:
     101                Expression * arg;
     102        };
     103
     104        InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
     105
     106        InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
     107
     108        std::list< Expression * > InitExpander::operator*() {
     109                return cur;
     110        }
     111
     112        InitExpander & InitExpander::operator++() {
     113                cur = expander->next( indices );
     114                return *this;
     115        }
     116
     117        // use array indices list to build switch statement
     118        void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
     119                indices.push_back( index );
     120                indices.push_back( dimension );
     121        }
     122
     123        void InitExpander::clearArrayIndices() {
     124                indices.clear();
     125        }
     126
     127        namespace {
     128                /// given index i, dimension d, initializer init, and callExpr f, generates
     129                ///   if (i < d) f(..., init)
     130                ///   ++i;
     131                /// so that only elements within the range of the array are constructed
     132                template< typename OutIterator >
     133                void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
     134                        UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
     135                        cond->get_args().push_back( index->clone() );
     136                        cond->get_args().push_back( dimension->clone() );
     137
     138                        std::list< Expression * > args = makeInitList( init );
     139                        callExpr->get_args().splice( callExpr->get_args().end(), args );
     140
     141                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     142
     143                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     144                        increment->get_args().push_back( new AddressExpr( index->clone() ) );
     145                        *out++ = new ExprStmt( noLabels, increment );
     146                }
     147
     148                template< typename OutIterator >
     149                void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     150                        if ( idx == idxEnd ) return;
     151                        Expression * index = *idx++;
     152                        assert( idx != idxEnd );
     153                        Expression * dimension = *idx++;
     154
     155                        // xxx - may want to eventually issue a warning here if we can detect
     156                        // that the number of elements exceeds to dimension of the array
     157                        if ( idx == idxEnd ) {
     158                                if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
     159                                        for ( Initializer * init : *listInit ) {
     160                                                buildCallExpr( callExpr->clone(), index, dimension, init, out );
     161                                        }
     162                                } else {
     163                                        buildCallExpr( callExpr->clone(), index, dimension, init, out );
     164                                }
     165                        } else {
     166                                std::list< Statement * > branches;
     167
     168                                unsigned long cond = 0;
     169                                ListInit * listInit = dynamic_cast< ListInit * >( init );
     170                                if ( ! listInit ) {
     171                                        // xxx - this shouldn't be an error, but need a way to
     172                                        // terminate without creating output, so should catch this error
     173                                        throw SemanticError( "unbalanced list initializers" );
     174                                }
     175
     176                                static UniqueName targetLabel( "L__autogen__" );
     177                                Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
     178                                for ( Initializer * init : *listInit ) {
     179                                        Expression * condition;
     180                                        // check for designations
     181                                        // if ( init-> ) {
     182                                                condition = new ConstantExpr( Constant::from_ulong( cond ) );
     183                                                ++cond;
     184                                        // } else {
     185                                        //      condition = // ... take designation
     186                                        //      cond = // ... take designation+1
     187                                        // }
     188                                        std::list< Statement * > stmts;
     189                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
     190                                        stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
     191                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
     192                                        branches.push_back( caseStmt );
     193                                }
     194                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
     195                                *out++ = new NullStmt( std::list<Label>{ switchLabel } );
     196                        }
     197                }
     198        }
     199
     200        // if array came with an initializer list: initialize each element
     201        // may have more initializers than elements in the array - need to check at each index that
     202        // we haven't exceeded size.
     203        // may have fewer initializers than elements in the array - need to default construct
     204        // remaining elements.
     205        // To accomplish this, generate switch statement, consuming all of expander's elements
     206        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     207                if ( ! init ) return NULL;
     208                CompoundStmt * block = new CompoundStmt( noLabels );
     209                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
     210                if ( block->get_kids().empty() ) {
     211                        delete block;
     212                        return NULL;
     213                } else {
     214                        init = NULL; // init was consumed in creating the list init
     215                        return block;
     216                }
     217        }
     218
     219        Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     220                return NULL;
     221        }
     222
     223        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
     224                return expander->buildListInit( dst, indices );
     225        }
     226
    55227        bool tryConstruct( ObjectDecl * objDecl ) {
    56228                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    57229                        (objDecl->get_init() == NULL ||
    58230                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() );
     231                        ! isDesignated( objDecl->get_init() )
     232                        && objDecl->get_storageClass() != DeclarationNode::Extern;
     233        }
     234
     235        class CallFinder : public Visitor {
     236        public:
     237                typedef Visitor Parent;
     238                CallFinder( const std::list< std::string > & names ) : names( names ) {}
     239
     240                virtual void visit( ApplicationExpr * appExpr ) {
     241                        handleCallExpr( appExpr );
     242                }
     243
     244                virtual void visit( UntypedExpr * untypedExpr ) {
     245                        handleCallExpr( untypedExpr );
     246                }
     247
     248                std::list< Expression * > * matches;
     249        private:
     250                const std::list< std::string > names;
     251
     252                template< typename CallExpr >
     253                void handleCallExpr( CallExpr * expr ) {
     254                        Parent::visit( expr );
     255                        std::string fname = getFunctionName( expr );
     256                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
     257                                matches->push_back( expr );
     258                        }
     259                }
     260        };
     261
     262        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
     263                static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
     264                finder.matches = &matches;
     265                maybeAccept( stmt, finder );
    60266        }
    61267
    62268        Expression * getCtorDtorCall( Statement * stmt ) {
    63                 if ( stmt == NULL ) return NULL;
    64                 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
    65                         return exprStmt->get_expr();
    66                 } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
    67                         // could also be a compound statement with a loop, in the case of an array
    68                         if( compoundStmt->get_kids().size() == 2 ) {
    69                                 // loop variable and loop
    70                                 ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
    71                                 assert( forStmt && forStmt->get_body() );
    72                                 return getCtorDtorCall( forStmt->get_body() );
    73                         } else if ( compoundStmt->get_kids().size() == 1 ) {
    74                                 // should be the call statement, but in any case there's only one option
    75                                 return getCtorDtorCall( compoundStmt->get_kids().front() );
    76                         } else {
    77                                 assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
    78                         }
    79                 } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
    80                         return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
    81                 } else {
    82                         // should never get here
    83                         assert( false && "encountered unknown call statement" );
    84                 }
    85         }
    86 
    87         bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    88                 Expression * callExpr = getCtorDtorCall( stmt );
    89                 if ( ! callExpr ) return false;
    90                 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
    91                 assert( appExpr );
    92                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
     269                std::list< Expression * > matches;
     270                collectCtorDtorCalls( stmt, matches );
     271                assert( matches.size() <= 1 );
     272                return matches.size() == 1 ? matches.front() : NULL;
     273        }
     274
     275        namespace {
     276                VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
     277                        assert( appExpr );
     278                        // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
     279                        return dynamic_cast< VariableExpr * >( appExpr->get_function() );
     280                }
     281        }
     282
     283        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
     284                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
     285                if ( ! appExpr ) return NULL;
     286                VariableExpr * function = getCalledFunction( appExpr );
    93287                assert( function );
    94288                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    95289                // will call all member dtors, and some members may have a user defined dtor.
    96                 FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
    97                 assert( funcType );
    98                 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
     290                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     291        }
     292
     293        bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
     294                std::list< Expression * > callExprs;
     295                collectCtorDtorCalls( stmt, callExprs );
     296                // if ( callExprs.empty() ) return false; // xxx - do I still need this check?
     297                return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
     298                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
     299                                assert( ! appExpr->get_function()->get_results().empty() );
     300                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
     301                                assert( funcType );
     302                                return funcType->get_parameters().size() == 1;
     303                        }
     304                        return false;
     305                });
    99306        }
    100307
     
    160367                else return NULL;
    161368        }
     369
     370        class ConstExprChecker : public Visitor {
     371        public:
     372                ConstExprChecker() : isConstExpr( true ) {}
     373
     374                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
     375                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
     376                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
     377                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     378                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
     379                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
     380                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
     381                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
     382                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
     383                // these might be okay?
     384                // virtual void visit( SizeofExpr *sizeofExpr );
     385                // virtual void visit( AlignofExpr *alignofExpr );
     386                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     387                // virtual void visit( OffsetofExpr *offsetofExpr );
     388                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     389                // virtual void visit( AttrExpr *attrExpr );
     390                // virtual void visit( CommaExpr *commaExpr );
     391                // virtual void visit( LogicalExpr *logicalExpr );
     392                // virtual void visit( ConditionalExpr *conditionalExpr );
     393                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     394                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
     395                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
     396                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
     397                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
     398                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     399
     400                bool isConstExpr;
     401        };
     402
     403        bool isConstExpr( Expression * expr ) {
     404                if ( expr ) {
     405                        ConstExprChecker checker;
     406                        expr->accept( checker );
     407                        return checker.isConstExpr;
     408                }
     409                return true;
     410        }
     411
     412        bool isConstExpr( Initializer * init ) {
     413                if ( init ) {
     414                        ConstExprChecker checker;
     415                        init->accept( checker );
     416                        return checker.isConstExpr;
     417                } // if
     418                // for all intents and purposes, no initializer means const expr
     419                return true;
     420        }
     421
    162422}
Note: See TracChangeset for help on using the changeset viewer.