Changes in / [becba789:8a443f4]


Ignore:
Location:
src
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rbecba789 r8a443f4  
    271271                printDesignators( init->get_designators() );
    272272                output << "{ ";
    273                 if ( init->begin_initializers() == init->end_initializers() ) {
     273                if ( init->begin() == init->end() ) {
    274274                        // illegal to leave initializer list empty for scalar initializers, but always legal to have 0
    275275                        output << "0";
    276276                } else {
    277                         genCommaList( init->begin_initializers(), init->end_initializers() );
     277                        genCommaList( init->begin(), init->end() );
    278278                }
    279279                output << " }";
  • src/GenPoly/DeclMutator.h

    rbecba789 r8a443f4  
    2828        class DeclMutator : public Mutator {
    2929        public:
     30                typedef Mutator Parent;
     31
    3032                DeclMutator();
    3133                virtual ~DeclMutator();
    32                
     34
     35                using Parent::mutate;
    3336                virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
    3437                virtual Statement* mutate(IfStmt *ifStmt);
     
    4245                /// Mutates a list of declarations with this visitor
    4346                void mutateDeclarationList(std::list< Declaration* >& decls);
    44                
     47
    4548                /// Called on entry to a new scope; overriders should call this as a super-class call
    4649                virtual void doBeginScope();
  • src/GenPoly/Specialize.cc

    rbecba789 r8a443f4  
    3131#include "Common/UniqueName.h"
    3232#include "Common/utility.h"
     33#include "InitTweak/InitTweak.h"
    3334
    3435namespace GenPoly {
     
    184185                mutateAll( appExpr->get_args(), *this );
    185186
    186                 // create thunks for the inferred parameters
    187                 for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    188                         inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
    189                 }
    190 
    191                 handleExplicitParams( appExpr );
     187                if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
     188                        // create thunks for the inferred parameters
     189                        // don't need to do this for intrinsic calls, because they aren't actually passed
     190                        for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
     191                                inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
     192                        }
     193
     194                        handleExplicitParams( appExpr );
     195                }
    192196
    193197                return appExpr;
  • src/InitTweak/FixGlobalInit.cc

    rbecba789 r8a443f4  
    4646                FunctionDecl * destroyFunction;
    4747        };
    48 
    49         class ConstExprChecker : public Visitor {
    50         public:
    51                 ConstExprChecker() : isConstExpr( true ) {}
    52 
    53                 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
    54                 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
    55                 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
    56                 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
    57                 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
    58                 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
    59                 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
    60                 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
    61                 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
    62                 // these might be okay?
    63                 // virtual void visit( SizeofExpr *sizeofExpr );
    64                 // virtual void visit( AlignofExpr *alignofExpr );
    65                 // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
    66                 // virtual void visit( OffsetofExpr *offsetofExpr );
    67                 // virtual void visit( OffsetPackExpr *offsetPackExpr );
    68                 // virtual void visit( AttrExpr *attrExpr );
    69                 // virtual void visit( CommaExpr *commaExpr );
    70                 // virtual void visit( LogicalExpr *logicalExpr );
    71                 // virtual void visit( ConditionalExpr *conditionalExpr );
    72                 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
    73                 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
    74                 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
    75                 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
    76                 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
    77                 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
    78 
    79                 bool isConstExpr;
    80         };
    81 
    82         bool isConstExpr( Initializer * init ) {
    83                 if ( init ) {
    84                         ConstExprChecker checker;
    85                         init->accept( checker );
    86                         return checker.isConstExpr;
    87                 } // if
    88                 // for all intents and purposes, no initializer means const expr
    89                 return true;
    90         }
    9148
    9249        void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
     
    14097                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    14198
    142                 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
    143                 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    14499                // C allows you to initialize objects with constant expressions
    145100                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    147102                // if ( isConstExpr( objDecl->get_init() ) ) return;
    148103
    149                 if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
    150                         // xxx - initialize each element of the array
    151                 } else {
    152                         // steal initializer from object and attach it to a new temporary
    153                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() );
    154                         objDecl->set_init( NULL );
    155                         initStatements.push_back( new DeclStmt( noLabels, newObj ) );
     104                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     105                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     106                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    156107
    157                         // copy construct objDecl using temporary
    158                         UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
    159                         init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    160                         init->get_args().push_back( new VariableExpr( newObj ) );
    161                         initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) );
    162 
    163                         // add destructor calls to global destroy function
    164                         UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
    165                         destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    166                         destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) );
     108                        Statement * dtor = ctorInit->get_dtor();
     109                        if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     110                                // don't need to call intrinsic dtor, because it does nothing, but
     111                                // non-intrinsic dtors must be called
     112                                destroyStatements.push_front( dtor );
     113                                ctorInit->set_dtor( NULL );
     114                        } // if
     115                        if ( Statement * ctor = ctorInit->get_ctor() ) {
     116                                initStatements.push_back( ctor );
     117                                objDecl->set_init( NULL );
     118                                ctorInit->set_ctor( NULL );
     119                        } else if ( Initializer * init = ctorInit->get_init() ) {
     120                                objDecl->set_init( init );
     121                                ctorInit->set_init( NULL );
     122                        } else {
     123                                // no constructor and no initializer, which is okay
     124                                objDecl->set_init( NULL );
     125                        } // if
     126                        delete ctorInit;
    167127                } // if
    168128        }
  • src/InitTweak/FixInit.cc

    rbecba789 r8a443f4  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "InitTweak.h"
    2021#include "FixInit.h"
    21 #include "InitTweak.h"
     22#include "FixGlobalInit.h"
    2223#include "ResolvExpr/Resolver.h"
    2324#include "ResolvExpr/typeops.h"
     
    8384                };
    8485
     86                // debug
    8587                struct printSet {
    8688                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    159161
    160162                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
     163
     164                        std::list< Declaration * > staticDtorDecls;
    161165                };
    162166
     
    171175        } // namespace
    172176
    173         void fix( std::list< Declaration * > & translationUnit ) {
     177        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     178                // fixes ConstructorInit for global variables. should happen before fixInitializers.
     179                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     180
    174181                InsertImplicitCalls::insert( translationUnit );
    175182                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    194201                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    195202                        FixInit fixer;
    196                         mutateAll( translationUnit, fixer );
     203
     204                        // can't use mutateAll, because need to insert declarations at top-level
     205                        // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
     206                        SemanticError errors;
     207                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     208                                try {
     209                                        *i = maybeMutate( *i, fixer );
     210                                        // if (! fixer.staticDtorDecls.empty() ) {
     211                                                translationUnit.splice( i, fixer.staticDtorDecls );
     212                                        // }
     213                                } catch( SemanticError &e ) {
     214                                        errors.append( e );
     215                                } // try
     216                        } // for
     217                        if ( ! errors.isEmpty() ) {
     218                                throw errors;
     219                        } // if
    197220                }
    198221
     
    422445                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    423446                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
     447                                                // originally wanted to take advantage of gcc nested functions, but
     448                                                // we get memory errors with this approach. To remedy this, create a
     449                                                // global static pointer that is set to refer to the object and make
     450                                                // the dtor-caller function global so that.
     451                                                //
    424452                                                // generate:
    425                                                 // static bool __objName_uninitialized = true;
    426                                                 // if (__objName_uninitialized) {
    427                                                 //   __ctor(__objName);
    428                                                 //   void dtor_atexit() {
    429                                                 //     __dtor(__objName);
     453                                                // T * __objName_static_ptrN;
     454                                                // void __objName_dtor_atexitN() {
     455                                                //   __dtor(__objName_static_ptrN);
     456                                                // }
     457                                                // int f(...) {
     458                                                //   ...
     459                                                //   static T __objName;
     460                                                //   static bool __objName_uninitialized = true;
     461                                                //   if (__objName_uninitialized) {
     462                                                //     __objName_ptr = &__objName;
     463                                                //     __ctor(__objName);
     464                                                //     on_exit(__objName_dtor_atexitN, &__objName);
     465                                                //     __objName_uninitialized = false;
    430466                                                //   }
    431                                                 //   on_exit(dtorOnExit, &__objName);
    432                                                 //   __objName_uninitialized = false;
     467                                                //   ...
    433468                                                // }
    434469
    435                                                 // generate first line
     470                                                static UniqueName ptrNamer( "_static_ptr" );
     471                                                static UniqueName dtorCallerNamer( "_dtor_atexit" );
     472
     473                                                // T * __objName_ptrN
     474                                                ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );
     475                                                objPtr->fixUniqueId();
     476
     477                                                // void __objName_dtor_atexitN(...) {...}
     478                                                // need to modify dtor call so that it refers to objPtr, since function will be global
     479                                                Statement * dtorStmt = ctorInit->get_dtor()->clone();
     480                                                ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );
     481                                                assert( dtor );
     482                                                delete dtor->get_args().front();
     483                                                dtor->get_args().front() = new VariableExpr( objPtr );
     484
     485                                                FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
     486                                                dtorCaller->fixUniqueId();
     487                                                dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
     488
     489                                                // static bool __objName_uninitialized = true
    436490                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    437491                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    439493                                                isUninitializedVar->fixUniqueId();
    440494
    441                                                 // void dtor_atexit(...) {...}
    442                                                 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    443                                                 dtorCaller->fixUniqueId();
    444                                                 dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor()->clone() );
    445 
    446                                                 // on_exit(dtor_atexit);
     495                                                // __objName_static_ptrN = &__objName;
     496                                                UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );
     497                                                ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );
     498                                                ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     499
     500                                                // atexit(dtor_atexit);
    447501                                                UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    448502                                                callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     
    457511                                                std::list< Statement * > & body = initStmts->get_kids();
    458512                                                body.push_back( ctor );
    459                                                 body.push_back( new DeclStmt( noLabels, dtorCaller ) );
     513                                                body.push_back( new ExprStmt( noLabels, ptrAssign ) );
    460514                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    461515                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
     
    465519                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    466520                                                stmtsToAddAfter.push_back( ifStmt );
     521
     522                                                // add pointer and dtor caller decls to list of decls that will be added into global scope
     523                                                staticDtorDecls.push_back( objPtr );
     524                                                staticDtorDecls.push_back( dtorCaller );
    467525                                        } else {
    468526                                                stmtsToAddAfter.push_back( ctor );
  • src/InitTweak/FixInit.h

    rbecba789 r8a443f4  
    2727  /// replace constructor initializers with expression statements
    2828  /// and unwrap basic C-style initializers
    29         void fix( std::list< Declaration * > & translationUnit );
     29        void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
    3030} // namespace
    3131
  • src/InitTweak/GenInit.cc

    rbecba789 r8a443f4  
    2626#include "SymTab/Autogen.h"
    2727#include "GenPoly/PolyMutator.h"
     28#include "GenPoly/DeclMutator.h"
    2829
    2930namespace InitTweak {
     
    5556          public:
    5657                /// create constructor and destructor statements for object declarations.
    57                 /// Destructors are inserted directly into the code, whereas constructors
    58                 /// will be added in after the resolver has run so that the initializer expression
    59                 /// is only removed if a constructor is found
     58                /// the actual call statements will be added in after the resolver has run
     59                /// so that the initializer expression is only removed if a constructor is found
     60                /// and the same destructor call is inserted in all of the appropriate locations.
    6061                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    61 
    62                 CtorDtor() : inFunction( false ) {}
    6362
    6463                virtual DeclarationWithType * mutate( ObjectDecl * );
    6564                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    66                 virtual Declaration* mutate( StructDecl *aggregateDecl );
    67                 virtual Declaration* mutate( UnionDecl *aggregateDecl );
    68                 virtual Declaration* mutate( EnumDecl *aggregateDecl );
    69                 virtual Declaration* mutate( TraitDecl *aggregateDecl );
    70                 virtual TypeDecl* mutate( TypeDecl *typeDecl );
    71                 virtual Declaration* mutate( TypedefDecl *typeDecl );
    72 
    73                 virtual Type * mutate( FunctionType *funcType );
     65                // should not traverse into any of these declarations to find objects
     66                // that need to be constructed or destructed
     67                virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
     68                virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
     69                virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     70                virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
     71                virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
     72                virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
     73
     74                virtual Type * mutate( FunctionType *funcType ) { return funcType; }
    7475
    7576          protected:
    76                 bool inFunction;
     77        };
     78
     79        class HoistArrayDimension : public GenPoly::DeclMutator {
     80          public:
     81                typedef GenPoly::DeclMutator Parent;
     82
     83                /// hoist dimension from array types in object declaration so that it uses a single
     84                /// const variable of type size_t, so that side effecting array dimensions are only
     85                /// computed once.
     86                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
     87
     88          private:
     89                virtual DeclarationWithType * mutate( ObjectDecl * objectDecl );
     90                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
     91                // should not traverse into any of these declarations to find objects
     92                // that need to be constructed or destructed
     93                virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
     94                virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
     95                virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     96                virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
     97                virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
     98                virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
     99
     100                virtual Type* mutate( FunctionType *funcType ) { return funcType; }
     101
     102                void hoist( Type * type );
     103
     104                DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass;
     105                bool inFunction = false;
    77106        };
    78107
    79108        void genInit( std::list< Declaration * > & translationUnit ) {
    80109                ReturnFixer::makeReturnTemp( translationUnit );
     110                HoistArrayDimension::hoistArrayDimension( translationUnit );
    81111                CtorDtor::generateCtorDtor( translationUnit );
    82112        }
     
    124154        }
    125155
     156        // precompute array dimension expression, because constructor generation may duplicate it,
     157        // which would be incorrect if it is a side-effecting computation.
     158        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
     159                HoistArrayDimension hoister;
     160                hoister.mutateDeclarationList( translationUnit );
     161        }
     162
     163        DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     164                storageclass = objectDecl->get_storageClass();
     165                DeclarationWithType * temp = Parent::mutate( objectDecl );
     166                hoist( objectDecl->get_type() );
     167                storageclass = DeclarationNode::NoStorageClass;
     168                return temp;
     169        }
     170
     171        void HoistArrayDimension::hoist( Type * type ) {
     172                // if in function, generate const size_t var
     173                static UniqueName dimensionName( "_array_dim" );
     174                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     175                        if ( ! inFunction ) return;
     176
     177                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
     178
     179                        // don't need to hoist dimension if it's a constexpr - only need to if there's potential
     180                        // for side effects.
     181                        if ( isConstExpr( arrayType->get_dimension() ) ) return;
     182
     183                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     184                        arrayDimension->get_type()->set_isConst( true );
     185
     186                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
     187                        addDeclaration( arrayDimension );
     188
     189                        hoist( arrayType->get_base() );
     190                        return;
     191                }
     192        }
     193
     194        DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
     195                bool oldInFunc = inFunction;
     196                inFunction = true;
     197                DeclarationWithType * decl = Parent::mutate( functionDecl );
     198                inFunction = oldInFunc;
     199                return decl;
     200        }
    126201
    127202        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    140215
    141216        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    142                 // hands off if designated or if @=
     217                // hands off if designated, if @=, or if extern
    143218                if ( tryConstruct( objDecl ) ) {
    144                         if ( inFunction ) {
    145                                 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
    146                                         // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
    147                                         // TODO: walk initializer and generate appropriate copy ctor if element has initializer
    148                                         std::list< Expression * > args = makeInitList( objDecl->get_init() );
    149                                         if ( args.empty() ) {
    150                                                 std::list< Statement * > ctor;
    151                                                 std::list< Statement * > dtor;
    152 
    153                                                 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) );
    154                                                 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false );
    155 
    156                                                 // Currently makeArrayFunction produces a single Statement - a CompoundStmt
    157                                                 // which  wraps everything that needs to happen. As such, it's technically
    158                                                 // possible to use a Statement ** in the above calls, but this is inherently
    159                                                 // unsafe, so instead we take the slightly less efficient route, but will be
    160                                                 // immediately informed if somehow the above assumption is broken. In this case,
    161                                                 // we could always wrap the list of statements at this point with a CompoundStmt,
    162                                                 // but it seems reasonable at the moment for this to be done by makeArrayFunction
    163                                                 // itself
    164                                                 assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) );
    165                                                 assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) );
    166                                                 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    167                                         } else {
    168                                                 // array came with an initializer list: initialize each element
    169                                                 // may have more initializers than elements in the array - need to check at each index that
    170                                                 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
    171                                                 // computation.
    172                                                 // may have fewer initializers than eleemnts in the array - need to default construct
    173                                                 // remaining elements.
    174                                                 // might be able to merge this with the case above.
    175                                         }
    176                                 } else {
    177                                         // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
    178                                         Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
    179                                         Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
    180 
    181                                         // need to remember init expression, in case no ctors exist
    182                                         // if ctor does exist, want to use ctor expression instead of init
    183                                         // push this decision to the resolver
    184                                         ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
    185                                         ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
    186                                         objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
    187                                 }
     219                        // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     220                        // for each constructable object
     221                        std::list< Statement * > ctor;
     222                        std::list< Statement * > dtor;
     223
     224                        InitExpander srcParam( objDecl->get_init() );
     225                        InitExpander nullParam( (Initializer *)NULL );
     226                        SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     227                        SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     228
     229                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     230                        // which  wraps everything that needs to happen. As such, it's technically
     231                        // possible to use a Statement ** in the above calls, but this is inherently
     232                        // unsafe, so instead we take the slightly less efficient route, but will be
     233                        // immediately informed if somehow the above assumption is broken. In this case,
     234                        // we could always wrap the list of statements at this point with a CompoundStmt,
     235                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     236                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     237                        // an array type does not have a dimension). In this case, it's fine to ignore
     238                        // the object for the purposes of construction.
     239                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     240                        if ( ctor.size() == 1 ) {
     241                                // need to remember init expression, in case no ctors exist
     242                                // if ctor does exist, want to use ctor expression instead of init
     243                                // push this decision to the resolver
     244                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     245                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    188246                        }
    189247                }
     
    193251        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    194252                // parameters should not be constructed and destructed, so don't mutate FunctionType
    195                 bool oldInFunc = inFunction;
    196253                mutateAll( functionDecl->get_oldDecls(), *this );
    197                 inFunction = true;
    198254                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    199                 inFunction = oldInFunc;
    200255                return functionDecl;
    201256        }
    202 
    203         // should not traverse into any of these declarations to find objects
    204         // that need to be constructed or destructed
    205         Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
    206         Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    207         Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
    208         Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
    209         TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
    210         Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
    211         Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; }
    212 
    213257} // namespace InitTweak
    214258
  • src/InitTweak/InitTweak.cc

    rbecba789 r8a443f4  
     1#include <algorithm>
    12#include "InitTweak.h"
    23#include "SynTree/Visitor.h"
     
    2021                };
    2122
    22                 class InitExpander : public Visitor {
     23                class InitFlattener : public Visitor {
    2324                        public:
    24                         InitExpander() {}
    2525                        virtual void visit( SingleInit * singleInit );
    2626                        virtual void visit( ListInit * listInit );
     
    2828                };
    2929
    30                 void InitExpander::visit( SingleInit * singleInit ) {
     30                void InitFlattener::visit( SingleInit * singleInit ) {
    3131                        argList.push_back( singleInit->get_value()->clone() );
    3232                }
    3333
    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 ) {
     34                void InitFlattener::visit( ListInit * listInit ) {
     35                        // flatten nested list inits
     36                        std::list<Initializer*>::iterator it = listInit->begin();
     37                        for ( ; it != listInit->end(); ++it ) {
    3838                                (*it)->accept( *this );
    3939                        }
     
    4242
    4343        std::list< Expression * > makeInitList( Initializer * init ) {
    44                 InitExpander expander;
    45                 maybeAccept( init, expander );
    46                 return expander.argList;
     44                InitFlattener flattener;
     45                maybeAccept( init, flattener );
     46                return flattener.argList;
    4747        }
    4848
     
    5353        }
    5454
     55        class InitExpander::ExpanderImpl {
     56        public:
     57                virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
     58                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
     59        };
     60
     61        class InitImpl : public InitExpander::ExpanderImpl {
     62        public:
     63                InitImpl( Initializer * init ) : init( init ) {}
     64
     65                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     66                        // this is wrong, but just a placeholder for now
     67                        // if ( ! flattened ) flatten( indices );
     68                        // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
     69                        return makeInitList( init );
     70                }
     71
     72                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
     73        private:
     74                Initializer * init;
     75        };
     76
     77        class ExprImpl : public InitExpander::ExpanderImpl {
     78        public:
     79                ExprImpl( Expression * expr ) : arg( expr ) {}
     80
     81                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     82                        std::list< Expression * > ret;
     83                        Expression * expr = maybeClone( arg );
     84                        if ( expr ) {
     85                                for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
     86                                        // go through indices and layer on subscript exprs ?[?]
     87                                        ++it;
     88                                        UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
     89                                        subscriptExpr->get_args().push_back( expr );
     90                                        subscriptExpr->get_args().push_back( (*it)->clone() );
     91                                        expr = subscriptExpr;
     92                                }
     93                                ret.push_back( expr );
     94                        }
     95                        return ret;
     96                }
     97
     98                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
     99        private:
     100                Expression * arg;
     101        };
     102
     103        InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
     104
     105        InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
     106
     107        std::list< Expression * > InitExpander::operator*() {
     108                return cur;
     109        }
     110
     111        InitExpander & InitExpander::operator++() {
     112                cur = expander->next( indices );
     113                return *this;
     114        }
     115
     116        // use array indices list to build switch statement
     117        void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
     118                indices.push_back( index );
     119                indices.push_back( dimension );
     120        }
     121
     122        void InitExpander::clearArrayIndices() {
     123                indices.clear();
     124        }
     125
     126        namespace {
     127                template< typename OutIterator >
     128                void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
     129                        UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
     130                        cond->get_args().push_back( index->clone() );
     131                        cond->get_args().push_back( dimension->clone() );
     132
     133                        std::list< Expression * > args = makeInitList( init );
     134                        callExpr->get_args().splice( callExpr->get_args().end(), args );
     135
     136                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     137
     138                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     139                        increment->get_args().push_back( new AddressExpr( index->clone() ) );
     140                        *out++ = new ExprStmt( noLabels, increment );
     141                }
     142
     143                template< typename OutIterator >
     144                void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     145                        if ( idx == idxEnd ) return;
     146                        Expression * index = *idx++;
     147                        assert( idx != idxEnd );
     148                        Expression * dimension = *idx++;
     149
     150                        if ( idx == idxEnd ) {
     151                                if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
     152                                        for ( Initializer * init : *listInit ) {
     153                                                dothething( callExpr->clone(), index, dimension, init, out );
     154                                        }
     155                                } else {
     156                                        dothething( callExpr->clone(), index, dimension, init, out );
     157                                }
     158                        } else {
     159                                std::list< Statement * > branches;
     160
     161                                unsigned long cond = 0;
     162                                ListInit * listInit = dynamic_cast< ListInit * >( init );
     163                                if ( ! listInit ) {
     164                                        // xxx - this shouldn't be an error, but need a way to
     165                                        // terminate without creating output, so should catch this error
     166                                        throw SemanticError( "unbalanced list initializers" );
     167                                }
     168                                for ( Initializer * init : *listInit ) {
     169                                        Expression * condition;
     170                                        // check for designations
     171                                        // if ( init-> ) {
     172                                                condition = new ConstantExpr( Constant::from_ulong( cond ) );
     173                                                ++cond;
     174                                        // } else {
     175                                        //      condition = // ... take designation
     176                                        //      cond = // ... take designation+1
     177                                        // }
     178                                        std::list< Statement * > stmts;
     179                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
     180                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
     181                                        branches.push_back( caseStmt );
     182                                }
     183                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
     184                        }
     185                }
     186        }
     187
     188        // if array came with an initializer list: initialize each element
     189        // may have more initializers than elements in the array - need to check at each index that
     190        // we haven't exceeded size.
     191        // may have fewer initializers than elements in the array - need to default construct
     192        // remaining elements.
     193        // To accomplish this, generate switch statement, consuming all of expander's elements
     194        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     195                if ( ! init ) return NULL;
     196                std::list< Statement * > results;
     197                build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
     198                assert( results.size() <= 1 );
     199                if ( results.empty() ) {
     200                        return NULL;
     201                } else {
     202                        init = NULL; // init was consumed in creating the list init
     203                        return results.front();
     204                }
     205                return ! results.empty() ? results.front() : NULL;
     206        }
     207
     208        Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     209                return NULL;
     210        }
     211
     212        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
     213                return expander->buildListInit( dst, indices );
     214        }
     215
    55216        bool tryConstruct( ObjectDecl * objDecl ) {
    56217                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    57218                        (objDecl->get_init() == NULL ||
    58219                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() );
     220                        ! isDesignated( objDecl->get_init() )
     221                        && objDecl->get_storageClass() != DeclarationNode::Extern;
     222        }
     223
     224        class CallFinder : public Visitor {
     225        public:
     226                typedef Visitor Parent;
     227                CallFinder( const std::list< std::string > & names ) : names( names ) {}
     228
     229                virtual void visit( ApplicationExpr * appExpr ) {
     230                        handleCallExpr( appExpr );
     231                }
     232
     233                virtual void visit( UntypedExpr * untypedExpr ) {
     234                        handleCallExpr( untypedExpr );
     235                }
     236
     237                std::list< Expression * > * matches;
     238        private:
     239                const std::list< std::string > names;
     240
     241                template< typename CallExpr >
     242                void handleCallExpr( CallExpr * expr ) {
     243                        Parent::visit( expr );
     244                        std::string fname = getFunctionName( expr );
     245                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
     246                                matches->push_back( expr );
     247                        }
     248                }
     249        };
     250
     251        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
     252                static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
     253                finder.matches = &matches;
     254                maybeAccept( stmt, finder );
    60255        }
    61256
    62257        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() );
     258                std::list< Expression * > matches;
     259                collectCtorDtorCalls( stmt, matches );
     260                assert( matches.size() <= 1 );
     261                return matches.size() == 1 ? matches.front() : NULL;
     262        }
     263
     264        namespace {
     265                VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
     266                        assert( appExpr );
     267                        // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
     268                        return dynamic_cast< VariableExpr * >( appExpr->get_function() );
     269                }
     270        }
     271
     272        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
     273                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
     274                if ( ! appExpr ) return NULL;
     275                VariableExpr * function = getCalledFunction( appExpr );
    93276                assert( function );
    94277                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    95278                // 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;
     279                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     280        }
     281
     282        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
     283                std::list< Expression * > callExprs;
     284                collectCtorDtorCalls( stmt, callExprs );
     285                // if ( callExprs.empty() ) return false; // xxx - do I still need this check?
     286                return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
     287                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
     288                                assert( ! appExpr->get_function()->get_results().empty() );
     289                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
     290                                assert( funcType );
     291                                return funcType->get_parameters().size() == 1;
     292                        }
     293                        return false;
     294                });
    99295        }
    100296
     
    160356                else return NULL;
    161357        }
     358
     359        class ConstExprChecker : public Visitor {
     360        public:
     361                ConstExprChecker() : isConstExpr( true ) {}
     362
     363                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
     364                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
     365                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
     366                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     367                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
     368                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
     369                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
     370                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
     371                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
     372                // these might be okay?
     373                // virtual void visit( SizeofExpr *sizeofExpr );
     374                // virtual void visit( AlignofExpr *alignofExpr );
     375                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     376                // virtual void visit( OffsetofExpr *offsetofExpr );
     377                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     378                // virtual void visit( AttrExpr *attrExpr );
     379                // virtual void visit( CommaExpr *commaExpr );
     380                // virtual void visit( LogicalExpr *logicalExpr );
     381                // virtual void visit( ConditionalExpr *conditionalExpr );
     382                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     383                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
     384                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
     385                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
     386                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
     387                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     388
     389                bool isConstExpr;
     390        };
     391
     392        bool isConstExpr( Expression * expr ) {
     393                if ( expr ) {
     394                        ConstExprChecker checker;
     395                        expr->accept( checker );
     396                        return checker.isConstExpr;
     397                }
     398                return true;
     399        }
     400
     401        bool isConstExpr( Initializer * init ) {
     402                if ( init ) {
     403                        ConstExprChecker checker;
     404                        init->accept( checker );
     405                        return checker.isConstExpr;
     406                } // if
     407                // for all intents and purposes, no initializer means const expr
     408                return true;
     409        }
     410
    162411}
  • src/InitTweak/InitTweak.h

    rbecba789 r8a443f4  
    2626// helper functions for initialization
    2727namespace InitTweak {
    28   /// transform Initializer into an argument list that can be passed to a call expression
    29   std::list< Expression * > makeInitList( Initializer * init );
     28        /// transform Initializer into an argument list that can be passed to a call expression
     29        std::list< Expression * > makeInitList( Initializer * init );
    3030
    31   /// True if the resolver should try to construct objDecl
    32   bool tryConstruct( ObjectDecl * objDecl );
     31        /// True if the resolver should try to construct objDecl
     32        bool tryConstruct( ObjectDecl * objDecl );
    3333
    34   /// True if the Initializer contains designations
    35   bool isDesignated( Initializer * init );
     34        /// True if the Initializer contains designations
     35        bool isDesignated( Initializer * init );
    3636
    37   /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
    38   /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
    39   /// Currently has assertions that make it less than fully general.
    40   bool isInstrinsicSingleArgCallStmt( Statement * expr );
     37  /// Non-Null if expr is a call expression whose target function is intrinsic
     38  ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
    4139
    42   /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    43   Expression * getCtorDtorCall( Statement * stmt );
     40        /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     41        /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
     42        /// Currently has assertions that make it less than fully general.
     43        bool isInstrinsicSingleArgCallStmt( Statement * expr );
    4444
    45   /// returns the name of the function being called
    46   std::string getFunctionName( Expression * expr );
     45        /// get all Ctor/Dtor call expressions from a Statement
     46        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    4747
    48   /// returns the argument to a call expression in position N indexed from 0
    49   Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     48        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     49        Expression * getCtorDtorCall( Statement * stmt );
    5050
    51   /// returns the base type of a PointerType or ArrayType, else returns NULL
    52   Type * getPointerBase( Type * );
     51        /// returns the name of the function being called
     52        std::string getFunctionName( Expression * expr );
    5353
    54   /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    55   Type * isPointerType( Type * );
     54        /// returns the argument to a call expression in position N indexed from 0
     55        Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     56
     57        /// returns the base type of a PointerType or ArrayType, else returns NULL
     58        Type * getPointerBase( Type * );
     59
     60        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     61        Type * isPointerType( Type * );
     62
     63        /// returns true if expr is trivially a compile-time constant
     64        bool isConstExpr( Expression * expr );
     65        bool isConstExpr( Initializer * init );
     66
     67        class InitExpander {
     68        public:
     69                // expand by stepping through init to get each list of arguments
     70                InitExpander( Initializer * init );
     71
     72                // always expand to expr
     73                InitExpander( Expression * expr );
     74
     75                // iterator-like interface
     76                std::list< Expression * > operator*();
     77                InitExpander & operator++();
     78
     79                // builds statement which has the same semantics as a C-style list initializer
     80                // (for array initializers) using callExpr as the base expression to perform initialization
     81                Statement * buildListInit( UntypedExpr * callExpr );
     82                void addArrayIndex( Expression * index, Expression * dimension );
     83                void clearArrayIndices();
     84
     85                class ExpanderImpl;
     86        private:
     87                std::shared_ptr< ExpanderImpl > expander;
     88                std::list< Expression * > cur;
     89
     90                // invariant: list of size 2N (elements come in pairs [index, dimension])
     91                typedef std::list< Expression * > IndexList;
     92                IndexList indices;
     93        };
    5694} // namespace
    5795
  • src/ResolvExpr/Resolver.cc

    rbecba789 r8a443f4  
    2424#include "SynTree/Initializer.h"
    2525#include "SymTab/Indexer.h"
     26#include "SymTab/Autogen.h"
    2627#include "Common/utility.h"
    2728#include "InitTweak/InitTweak.h"
     
    4142
    4243                virtual void visit( ArrayType * at );
     44                virtual void visit( PointerType * at );
    4345
    4446                virtual void visit( ExprStmt *exprStmt );
     
    5254                virtual void visit( BranchStmt *branchStmt );
    5355                virtual void visit( ReturnStmt *returnStmt );
    54                 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5556
    5657                virtual void visit( SingleInit *singleInit );
     
    5960          private:
    6061        typedef std::list< Initializer * >::iterator InitIterator;
     62
     63                template< typename PtrType >
     64                void handlePtrType( PtrType * type );
    6165
    6266          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    192196        }
    193197
     198        template< typename PtrType >
     199        void Resolver::handlePtrType( PtrType * type ) {
     200                if ( type->get_dimension() ) {
     201                        CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
     202                        Expression *newExpr = findSingleExpression( castExpr, *this );
     203                        delete type->get_dimension();
     204                        type->set_dimension( newExpr );
     205                }
     206        }
     207
    194208        void Resolver::visit( ArrayType * at ) {
    195                 if ( at->get_dimension() ) {
    196                         BasicType arrayLenType = BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    197                         CastExpr *castExpr = new CastExpr( at->get_dimension(), arrayLenType.clone() );
    198                         Expression *newExpr = findSingleExpression( castExpr, *this );
    199                         delete at->get_dimension();
    200                         at->set_dimension( newExpr );
    201                 }
     209                handlePtrType( at );
    202210                Visitor::visit( at );
     211        }
     212
     213        void Resolver::visit( PointerType * pt ) {
     214                handlePtrType( pt );
     215                Visitor::visit( pt );
    203216        }
    204217
     
    422435
    423436        void Resolver::visit( ListInit * listInit ) {
    424                 InitIterator iter = listInit->begin_initializers();
    425                 InitIterator end = listInit->end_initializers();
     437                InitIterator iter = listInit->begin();
     438                InitIterator end = listInit->end();
    426439
    427440                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     
    525538                        ctorInit->set_ctor( NULL );
    526539                }
    527                 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
     540                if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
    528541                        delete ctorInit->get_dtor();
    529542                        ctorInit->set_dtor( NULL );
    530543                }
    531         }
    532 
    533         void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
    534                 // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
    535                 // Do this through a cast expression to greatly simplify the code.
    536                 Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
    537                 assert( callExpr );
    538                 Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
    539                 Type * type = 0;
    540 
    541                 // need to find the type of the first argument, which is unfortunately not uniform since array construction
    542                 // includes an untyped '+' expression.
    543                 if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {
    544                         // constructee is <array>+<index>
    545                         // get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed
    546                         Expression * arr = InitTweak::getCallArg( plusExpr, 0 );
    547                         assert( dynamic_cast< VariableExpr * >( arr ) || dynamic_cast< MemberExpr *>( arr ) );
    548                         assert( arr && arr->get_results().size() == 1 );
    549                         type = arr->get_results().front()->clone();
    550                 } else {
    551                         // otherwise, constructing a plain object, which means the object's address is being taken.
    552                         // Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the
    553                         // type of the VariableExpr to do so.
    554                         assert( constructee->get_results().size() == 1 );
    555                         AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
    556                         assert( addrExpr && addrExpr->get_results().size() == 1 );
    557                         type = addrExpr->get_results().front()->clone();
    558                 }
    559                 // cast to T* with qualifiers removed.
    560                 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    561                 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    562                 // remove lvalue as a qualifier, this can change to
    563                 //   type->get_qualifiers() = Type::Qualifiers();
    564                 Type * base = InitTweak::getPointerBase( type );
    565                 assert( base );
    566                 base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
    567                 // if pointer has lvalue qualifier, cast won't appear in output
    568                 type->set_isLvalue( false );
    569                 constructee = new CastExpr( constructee, type );
    570 
    571                 // finally, resolve the ctor/dtor
    572                 impCtorDtorStmt->get_callStmt()->accept( *this );
    573544        }
    574545} // namespace ResolvExpr
  • src/SymTab/Autogen.cc

    rbecba789 r8a443f4  
    2626
    2727namespace SymTab {
     28        Type * SizeType = 0;
     29
    2830        class AutogenerateRoutines : public Visitor {
    2931                public:
     
    5961        bool isUnnamedBitfield( ObjectDecl * obj ) {
    6062                return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
    61         }
    62 
    63         template< typename OutputIterator >
    64         void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
    65                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
    66                 // unnamed bit fields are not copied as they cannot be accessed
    67                 if ( isUnnamedBitfield( obj ) ) return;
    68 
    69                 // want to be able to generate assignment, ctor, and dtor generically,
    70                 // so fname is either ?=?, ?{}, or ^?{}
    71                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    72 
    73                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    74                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    75 
    76                 // do something special for unnamed members
    77                 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
    78                 fExpr->get_args().push_back( dstselect );
    79 
    80                 if ( src ) {
    81                         fExpr->get_args().push_back( src );
    82                 }
    83 
    84                 Statement * callStmt = new ExprStmt( noLabels, fExpr );
    85                 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
    86                         // implicitly generated ctor/dtor calls should be wrapped
    87                         // so that later passes are aware they were generated.
    88                         // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    89                         // because this causes the address to be taken at codegen, which is illegal in C.
    90                         callStmt = new ImplicitCtorDtorStmt( callStmt );
    91                 }
    92                 *out++ = callStmt;
    9363        }
    9464
     
    219189                }
    220190
     191                InitTweak::InitExpander srcParam( src );
     192
    221193                // assign to destination (and return value if generic)
    222                 if ( ArrayType *array = dynamic_cast< ArrayType * >( field->get_type() ) ) {
    223                         UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    224                         derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    225                         Expression *dstselect = new MemberExpr( field, derefExpr );
    226 
    227                         makeArrayFunction( src, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
    228                         if ( isGeneric && returnVal ) {
    229                                 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
    230                                 derefRet->get_args().push_back( new VariableExpr( returnVal ) );
    231                                 Expression *retselect = new MemberExpr( field, derefRet );
    232 
    233                                 makeArrayFunction( src, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
    234                         }
    235                 } else {
    236                         makeScalarFunction( src, dstParam, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
    237                         if ( isGeneric && returnVal ) makeScalarFunction( src, returnVal, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
     194                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     195                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     196                Expression *dstselect = new MemberExpr( field, derefExpr );
     197                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     198
     199                if ( isGeneric && returnVal ) {
     200                        UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
     201                        derefRet->get_args().push_back( new VariableExpr( returnVal ) );
     202                        Expression *retselect = new MemberExpr( field, derefRet );
     203                        genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    238204                } // if
    239205        }
  • src/SymTab/Autogen.h

    rbecba789 r8a443f4  
    2222#include "SynTree/Declaration.h"
    2323#include "SynTree/Initializer.h"
     24#include "InitTweak/InitTweak.h"
    2425
    2526namespace SymTab {
    26   /// Generates assignment operators, constructors, and destructor for aggregate types as required
    27   void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     27        /// Generates assignment operators, constructors, and destructor for aggregate types as required
     28        void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2829
    29   // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
    30   // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
     30        /// returns true if obj's name is the empty string and it has a bitfield width
     31        bool isUnnamedBitfield( ObjectDecl * obj );
    3132
    32   /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    33   /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    34   template< typename OutputIterator >
    35   void makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) {
    36     static UniqueName indexName( "_index" );
     33        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     34        /// such as in determining array dimension type
     35        extern Type * SizeType;
    3736
    38     // for a flexible array member nothing is done -- user must define own assignment
    39     if ( ! array->get_dimension() ) return;
     37        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     38        template< typename OutputIterator >
     39        void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    4040
    41     Expression * begin, * end, * update, * cmp;
    42     if ( forward ) {
    43       // generate: for ( int i = 0; i < 0; ++i )
    44       begin = new NameExpr( "0" );
    45       end = array->get_dimension()->clone();
    46       cmp = new NameExpr( "?<?" );
    47       update = new NameExpr( "++?" );
    48     } else {
    49       // generate: for ( int i = N-1; i >= 0; --i )
    50       begin = new UntypedExpr( new NameExpr( "?-?" ) );
    51       ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    52       ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
    53       end = new NameExpr( "0" );
    54       cmp = new NameExpr( "?>=?" );
    55       update = new NameExpr( "--?" );
     41        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     42        template< typename OutputIterator >
     43        void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
     44                // want to be able to generate assignment, ctor, and dtor generically,
     45                // so fname is either ?=?, ?{}, or ^?{}
     46                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     47
     48                // do something special for unnamed members
     49                dstParam = new AddressExpr( dstParam );
     50                if ( addCast ) {
     51                        // cast to T* with qualifiers removed, so that qualified objects can be constructed
     52                        // and destructed with the same functions as non-qualified objects.
     53                        // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     54                        // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     55                        // remove lvalue as a qualifier, this can change to
     56                        //   type->get_qualifiers() = Type::Qualifiers();
     57                        assert( type );
     58                        Type * castType = type->clone();
     59                        castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     60                        castType->set_isLvalue( true ); // xxx - might not need this
     61                        dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     62                }
     63                fExpr->get_args().push_back( dstParam );
     64
     65    Statement * listInit = srcParam.buildListInit( fExpr );
     66    if ( listInit ) {
     67      *out++ = listInit;
    5668    }
    5769
    58     ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     70    std::list< Expression * > args = *++srcParam;
     71    fExpr->get_args().splice( fExpr->get_args().end(), args );
    5972
    60     UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    61     init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    62     init->get_args().push_back( begin );
    63     index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     73                *out++ = new ExprStmt( noLabels, fExpr );
    6474
    65     UntypedExpr *cond = new UntypedExpr( cmp );
    66     cond->get_args().push_back( new VariableExpr( index ) );
    67     cond->get_args().push_back( end );
     75    srcParam.clearArrayIndices();
     76        }
    6877
    69     UntypedExpr *inc = new UntypedExpr( update );
    70     inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     78        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     79        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     80        template< typename OutputIterator >
     81        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     82                static UniqueName indexName( "_index" );
    7183
    72     // want to be able to generate assignment, ctor, and dtor generically,
    73     // so fname is either ?=?, ?{}, or ^?{}
    74     UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     84                // for a flexible array member nothing is done -- user must define own assignment
     85                if ( ! array->get_dimension() ) return ;
    7586
    76     UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
    77     dstIndex->get_args().push_back( dstParam );
    78     dstIndex->get_args().push_back( new VariableExpr( index ) );
    79     fExpr->get_args().push_back( dstIndex );
     87                Expression * begin, * end, * update, * cmp;
     88                if ( forward ) {
     89                        // generate: for ( int i = 0; i < 0; ++i )
     90                        begin = new NameExpr( "0" );
     91                        end = array->get_dimension()->clone();
     92                        cmp = new NameExpr( "?<?" );
     93                        update = new NameExpr( "++?" );
     94                } else {
     95                        // generate: for ( int i = N-1; i >= 0; --i )
     96                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
     97                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     98                        ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
     99                        end = new NameExpr( "0" );
     100                        cmp = new NameExpr( "?>=?" );
     101                        update = new NameExpr( "--?" );
     102                }
    80103
    81     // srcParam is NULL for default ctor/dtor
    82     if ( srcParam ) {
    83       UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    84       srcIndex->get_args().push_back( srcParam );
    85       srcIndex->get_args().push_back( new VariableExpr( index ) );
    86       fExpr->get_args().push_back( srcIndex );
     104                ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     105
     106                UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     107                init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     108                init->get_args().push_back( begin );
     109                index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     110
     111                UntypedExpr *cond = new UntypedExpr( cmp );
     112                cond->get_args().push_back( new VariableExpr( index ) );
     113                cond->get_args().push_back( end );
     114
     115                UntypedExpr *inc = new UntypedExpr( update );
     116                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     117
     118                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     119                dstIndex->get_args().push_back( dstParam );
     120                dstIndex->get_args().push_back( new VariableExpr( index ) );
     121                dstParam = dstIndex;
     122
     123                // srcParam must keep track of the array indices to build the
     124                // source parameter and/or array list initializer
     125                srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
     126
     127                // if ( srcParam ) {
     128                //      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     129                //      srcIndex->get_args().push_back( srcParam );
     130                //      srcIndex->get_args().push_back( new VariableExpr( index ) );
     131                //      srcParam = srcIndex;
     132                // }
     133
     134                // for stmt's body, eventually containing call
     135                CompoundStmt * body = new CompoundStmt( noLabels );
     136                genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     137
     138                // block containing for stmt and index variable
     139                std::list<Statement *> initList;
     140                CompoundStmt * block = new CompoundStmt( noLabels );
     141                block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     142                block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     143
     144                *out++ = block;
     145        }
     146
     147        template< typename OutputIterator >
     148        void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     149                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     150                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     151                } else {
     152                        genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     153                }
     154        }
     155
     156        /// inserts into out a generated call expression to function fname with arguments dstParam
     157        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     158        /// object being constructed. The function wraps constructor and destructor calls in an
     159        /// ImplicitCtorDtorStmt node.
     160        template< typename OutputIterator >
     161        void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     162                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     163                assert( obj );
     164                // unnamed bit fields are not copied as they cannot be accessed
     165                if ( isUnnamedBitfield( obj ) ) return;
     166
     167                bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
     168                std::list< Statement * > stmts;
     169                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
     170
     171                // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
     172                assert( stmts.size() <= 1 );
     173    if ( stmts.size() == 1 ) {
     174                Statement * callStmt = stmts.front();
     175                if ( addCast ) {
     176                        // implicitly generated ctor/dtor calls should be wrapped
     177                        // so that later passes are aware they were generated.
     178                        // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     179                        // because this causes the address to be taken at codegen, which is illegal in C.
     180                        callStmt = new ImplicitCtorDtorStmt( callStmt );
     181                }
     182                *out++ = callStmt;
    87183    }
    88 
    89     std::list<Statement *> initList;
    90     CompoundStmt * block = new CompoundStmt( noLabels );
    91     block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    92     block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) );
    93 
    94     Statement * stmt = block;
    95     if ( fname == "?{}" || fname == "^?{}" ) {
    96       // implicitly generated ctor/dtor calls should be wrapped
    97       // so that later passes are aware they were generated
    98       stmt = new ImplicitCtorDtorStmt( stmt );
    99     }
    100     *out++ = stmt;
    101   }
     184        }
    102185} // namespace SymTab
    103186#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

    rbecba789 r8a443f4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixFunction.cc -- 
     7// FixFunction.cc --
    88//
    99// Author           : Richard C. Bilson
     
    4444
    4545        Type * FixFunction::mutate(ArrayType *arrayType) {
    46                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
     46                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
     47                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
    4748                delete arrayType;
    4849                return pointerType;
  • src/SymTab/Validate.cc

    rbecba789 r8a443f4  
    174174
    175175                virtual void visit( FunctionDecl *funcDecl );
    176 };
     176        };
    177177
    178178        class CompoundLiteral : public GenPoly::DeclMutator {
     
    191191                EliminateTypedef::eliminateTypedef( translationUnit );
    192192                HoistStruct::hoistStruct( translationUnit );
     193                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1
    193194                acceptAll( translationUnit, pass1 );
    194195                acceptAll( translationUnit, pass2 );
    195196                ReturnChecker::checkFunctionReturns( translationUnit );
    196                 mutateAll( translationUnit, compoundliteral );
    197                 autogenerateRoutines( translationUnit );
     197                compoundliteral.mutateDeclarationList( translationUnit );
    198198                acceptAll( translationUnit, pass3 );
    199199                VerifyCtorDtor::verify( translationUnit );
     
    490490                EliminateTypedef eliminator;
    491491                mutateAll( translationUnit, eliminator );
     492                if ( eliminator.typedefNames.count( "size_t" ) ) {
     493                        // grab and remember declaration of size_t
     494                        SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone();
     495                } else {
     496                        // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
     497                        // eventually should have a warning for this case.
     498                        SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     499                }
    492500                filter( translationUnit, isTypedef, true );
     501
    493502        }
    494503
     
    518527        Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
    519528                Declaration *ret = Mutator::mutate( tyDecl );
     529
    520530                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    521531                        // typedef to the same name from the same scope
  • src/SynTree/Expression.cc

    rbecba789 r8a443f4  
    344344}
    345345
     346//// is this right? It's cloning the member, but the member is a declaration so probably shouldn't be cloned...
    346347MemberExpr::MemberExpr( const MemberExpr &other ) :
    347                 Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
     348                Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
    348349}
    349350
    350351MemberExpr::~MemberExpr() {
    351         delete member;
     352        // delete member;
    352353        delete aggregate;
    353354}
  • src/SynTree/Initializer.h

    rbecba789 r8a443f4  
    9393        std::list<Initializer*> &get_initializers() { return initializers; }
    9494
    95         std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); }
    96         std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
     95        typedef std::list<Initializer*>::iterator iterator;
     96        iterator begin() { return initializers.begin(); }
     97        iterator end() { return initializers.end(); }
    9798
    9899        virtual ListInit *clone() const { return new ListInit( *this ); }
  • src/main.cc

    rbecba789 r8a443f4  
    4242#include "InitTweak/GenInit.h"
    4343#include "InitTweak/FixInit.h"
    44 #include "InitTweak/FixGlobalInit.h"
    4544//#include "Explain/GenProlog.h"
    4645//#include "Try/Visit.h"
     
    282281                OPTPRINT( "fixNames" )
    283282                CodeGen::fixNames( translationUnit );
    284                 OPTPRINT( "fixGlobalInit" );
    285                 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
    286283                OPTPRINT( "tweakInit" )
    287284                InitTweak::genInit( translationUnit );
     
    304301                }
    305302
     303                // fix ObjectDecl - replaces ConstructorInit nodes
    306304                OPTPRINT( "fixInit" )
    307                 // fix ObjectDecl - replaces ConstructorInit nodes
    308                 InitTweak::fix( translationUnit );
     305                InitTweak::fix( translationUnit, filename, libcfap || treep );
    309306                if ( ctorinitp ) {
    310307                        dump ( translationUnit );
  • src/tests/.expect/64/extension.txt

    rbecba789 r8a443f4  
    100100    ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2));
    101101}
    102 __attribute__ ((constructor(),)) static void _init_extension(void){
    103     int _global_init0;
    104     ((void)((*((int *)(&__a__i_1)))=_global_init0) /* ?{} */);
    105     int _global_init1;
    106     ((void)((*((int *)(&__b__i_1)))=_global_init1) /* ?{} */);
    107     int _global_init2;
    108     ((void)((*((int *)(&__c__i_1)))=_global_init2) /* ?{} */);
    109 }
    110 __attribute__ ((destructor(),)) static void _destroy_extension(void){
    111     ((void)((*((int *)(&__c__i_1)))) /* ^?{} */);
    112     ((void)((*((int *)(&__b__i_1)))) /* ^?{} */);
    113     ((void)((*((int *)(&__a__i_1)))) /* ^?{} */);
    114 }
  • src/tests/init_once.c

    rbecba789 r8a443f4  
    9292init_once y = x;
    9393
     94void static_variable() {
     95        static init_once x;
     96}
     97
    9498int main() {
    9599        // local variables
     
    179183                }
    180184        }
     185
     186        // function-scoped static variable
     187        for (int i = 0; i < 10; i++) {
     188                static_variable();
     189        }
    181190}
    182191
Note: See TracChangeset for help on using the changeset viewer.