Changes in / [e4957e7:29e8bf5]


Ignore:
Location:
src
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/DeclMutator.h

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
     157                HoistArrayDimension hoister;
     158                hoister.mutateDeclarationList( translationUnit );
     159        }
     160
     161        DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     162                storageclass = objectDecl->get_storageClass();
     163                DeclarationWithType * temp = Parent::mutate( objectDecl );
     164                hoist( objectDecl->get_type() );
     165                storageclass = DeclarationNode::NoStorageClass;
     166                return temp;
     167        }
     168
     169        void HoistArrayDimension::hoist( Type * type ) {
     170                // if in function, generate const size_t var
     171                static UniqueName dimensionName( "_array_dim" );
     172                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     173                        if ( ! inFunction ) return;
     174
     175                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
     176
     177                        // don't need to hoist dimension if it's a constexpr - only need to if there's potential
     178                        // for side effects.
     179                        if ( isConstExpr( arrayType->get_dimension() ) ) return;
     180
     181                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     182                        arrayDimension->get_type()->set_isConst( true );
     183
     184                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
     185                        addDeclaration( arrayDimension );
     186
     187                        hoist( arrayType->get_base() );
     188                        return;
     189                }
     190        }
     191
     192        DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
     193                bool oldInFunc = inFunction;
     194                inFunction = true;
     195                DeclarationWithType * decl = Parent::mutate( functionDecl );
     196                inFunction = oldInFunc;
     197                return decl;
     198        }
    126199
    127200        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    140213
    141214        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    142                 // hands off if designated or if @=
     215                // hands off if designated, if @=, or if extern
    143216                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() ) );
     217                        if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
     218                                // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
     219                                // TODO: walk initializers and generate appropriate ctor if element has initializer.
     220                                // Initializer could be nested (depends on the depth of the array type on the object)
     221
     222                                std::list< Expression * > args = makeInitList( objDecl->get_init() );
     223                                if ( args.empty() ) {
     224                                        std::list< Statement * > ctor;
     225                                        std::list< Statement * > dtor;
     226
     227                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     228                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     229
     230                                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     231                                        // which  wraps everything that needs to happen. As such, it's technically
     232                                        // possible to use a Statement ** in the above calls, but this is inherently
     233                                        // unsafe, so instead we take the slightly less efficient route, but will be
     234                                        // immediately informed if somehow the above assumption is broken. In this case,
     235                                        // we could always wrap the list of statements at this point with a CompoundStmt,
     236                                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     237                                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     238                                        // an array type does not have a dimension). In this case, it's fine to ignore
     239                                        // the object for the purposes of construction.
     240                                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     241                                        if ( ctor.size() == 1 ) {
     242                                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    166243                                                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.
    175244                                        }
    176245                                } 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() ) );
     246                                        // array came with an initializer list: initialize each element
     247                                        // may have more initializers than elements in the array - need to check at each index that
     248                                        // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
     249                                        // computation.
     250                                        // may have fewer initializers than elements in the array - need to default construct
     251                                        // remaining elements.
     252                                        // might be able to merge this with the case above.
     253
    187254                                }
     255                        } else {
     256                                // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
     257                                Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
     258                                Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
     259
     260                                // need to remember init expression, in case no ctors exist
     261                                // if ctor does exist, want to use ctor expression instead of init
     262                                // push this decision to the resolver
     263                                ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
     264                                ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
     265                                objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
    188266                        }
    189267                }
     
    193271        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    194272                // parameters should not be constructed and destructed, so don't mutate FunctionType
    195                 bool oldInFunc = inFunction;
    196273                mutateAll( functionDecl->get_oldDecls(), *this );
    197                 inFunction = true;
    198274                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    199                 inFunction = oldInFunc;
    200275                return functionDecl;
    201276        }
    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 
    213277} // namespace InitTweak
    214278
  • src/InitTweak/InitTweak.cc

    re4957e7 r29e8bf5  
    5757                        (objDecl->get_init() == NULL ||
    5858                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() );
     59                        ! isDesignated( objDecl->get_init() )
     60                        && objDecl->get_storageClass() != DeclarationNode::Extern;
    6061        }
    6162
     
    8485                }
    8586        }
     87        namespace {
     88                VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
     89                        assert( appExpr );
     90                        return dynamic_cast< VariableExpr * >( appExpr->get_function() );
     91                }
     92        }
     93
     94        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
     95                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
     96                if ( ! appExpr ) return NULL;
     97                VariableExpr * function = getCalledFunction( appExpr );
     98                assert( function );
     99                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
     100                // will call all member dtors, and some members may have a user defined dtor.
     101                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     102        }
    86103
    87104        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    88105                Expression * callExpr = getCtorDtorCall( stmt );
    89106                if ( ! callExpr ) return false;
    90                 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
    91                 assert( appExpr );
    92                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    93                 assert( function );
    94                 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    95                 // 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;
     107                if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
     108                        assert( ! appExpr->get_function()->get_results().empty() );
     109                        FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
     110                        assert( funcType );
     111                        return funcType->get_parameters().size() == 1;
     112                }
     113                return false;
    99114        }
    100115
     
    160175                else return NULL;
    161176        }
     177
     178        class ConstExprChecker : public Visitor {
     179        public:
     180                ConstExprChecker() : isConstExpr( true ) {}
     181
     182                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
     183                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
     184                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
     185                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     186                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
     187                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
     188                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
     189                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
     190                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
     191                // these might be okay?
     192                // virtual void visit( SizeofExpr *sizeofExpr );
     193                // virtual void visit( AlignofExpr *alignofExpr );
     194                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     195                // virtual void visit( OffsetofExpr *offsetofExpr );
     196                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     197                // virtual void visit( AttrExpr *attrExpr );
     198                // virtual void visit( CommaExpr *commaExpr );
     199                // virtual void visit( LogicalExpr *logicalExpr );
     200                // virtual void visit( ConditionalExpr *conditionalExpr );
     201                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     202                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
     203                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
     204                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
     205                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
     206                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     207
     208                bool isConstExpr;
     209        };
     210
     211        bool isConstExpr( Expression * expr ) {
     212                if ( expr ) {
     213                        ConstExprChecker checker;
     214                        expr->accept( checker );
     215                        return checker.isConstExpr;
     216                }
     217                return true;
     218        }
     219
     220        bool isConstExpr( Initializer * init ) {
     221                if ( init ) {
     222                        ConstExprChecker checker;
     223                        init->accept( checker );
     224                        return checker.isConstExpr;
     225                } // if
     226                // for all intents and purposes, no initializer means const expr
     227                return true;
     228        }
     229
    162230}
  • src/InitTweak/InitTweak.h

    re4957e7 r29e8bf5  
    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 the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     46        Expression * getCtorDtorCall( Statement * stmt );
    4747
    48   /// returns the argument to a call expression in position N indexed from 0
    49   Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     48        /// returns the name of the function being called
     49        std::string getFunctionName( Expression * expr );
    5050
    51   /// returns the base type of a PointerType or ArrayType, else returns NULL
    52   Type * getPointerBase( Type * );
     51        /// returns the argument to a call expression in position N indexed from 0
     52        Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    5353
    54   /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    55   Type * isPointerType( Type * );
     54        /// returns the base type of a PointerType or ArrayType, else returns NULL
     55        Type * getPointerBase( Type * );
     56
     57        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     58        Type * isPointerType( Type * );
     59
     60        /// returns true if expr is trivially a compile-time constant
     61        bool isConstExpr( Expression * expr );
     62        bool isConstExpr( Initializer * init );
    5663} // namespace
    5764
  • src/ResolvExpr/Resolver.cc

    re4957e7 r29e8bf5  
    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 );
     
    5961          private:
    6062        typedef std::list< Initializer * >::iterator InitIterator;
     63
     64                template< typename PtrType >
     65                void handlePtrType( PtrType * type );
    6166
    6267          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    192197        }
    193198
     199        template< typename PtrType >
     200        void Resolver::handlePtrType( PtrType * type ) {
     201                if ( type->get_dimension() ) {
     202                        CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
     203                        Expression *newExpr = findSingleExpression( castExpr, *this );
     204                        delete type->get_dimension();
     205                        type->set_dimension( newExpr );
     206                }
     207        }
     208
    194209        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                 }
     210                handlePtrType( at );
    202211                Visitor::visit( at );
     212        }
     213
     214        void Resolver::visit( PointerType * pt ) {
     215                handlePtrType( pt );
     216                Visitor::visit( pt );
    203217        }
    204218
     
    537551                assert( callExpr );
    538552                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                 }
     553
     554                // the first argument will always be &<expr>
     555                AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
     556                assert( addrExpr );
     557
     558                // need to find the type of the first argument. In the case of an array,
     559                // need to remove one ArrayType layer from the type for each subscript expression.
     560                Expression * addressee = addrExpr->get_arg();
     561                int numLayers = 0;
     562                while ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( addressee ) ) {
     563                        assert( InitTweak::getFunctionName( untypedExpr ) == "?[?]" );
     564                        addressee = InitTweak::getCallArg( untypedExpr, 0 );
     565                        numLayers++;
     566                }
     567                assert( addressee->get_results().size() == 1 );
     568                Type * type = addressee->get_results().front();
     569                for ( int i = 0; i < numLayers; i++ ) {
     570                        type = InitTweak::getPointerBase( type );
     571                        assert( type && "Expected pointer or array type. May have generated too many ?[?] calls." );
     572                }
     573
    559574                // cast to T* with qualifiers removed.
    560575                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     
    562577                // remove lvalue as a qualifier, this can change to
    563578                //   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 );
     579                assert( type );
     580                type = type->clone();
     581                type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     582                type = new PointerType( Type::Qualifiers(), type );
    569583                constructee = new CastExpr( constructee, type );
    570584
  • src/SymTab/Autogen.cc

    re4957e7 r29e8bf5  
    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
     
    220190
    221191                // 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() ) );
     192                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     193                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     194                Expression *dstselect = new MemberExpr( field, derefExpr );
     195                genImplicitCall( src, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     196
     197                if ( isGeneric && returnVal ) {
     198                        UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
     199                        derefRet->get_args().push_back( new VariableExpr( returnVal ) );
     200                        Expression *retselect = new MemberExpr( field, derefRet );
     201                        genImplicitCall( src, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    238202                } // if
    239203        }
  • src/SymTab/Autogen.h

    re4957e7 r29e8bf5  
    2424
    2525namespace SymTab {
    26   /// Generates assignment operators, constructors, and destructor for aggregate types as required
    27   void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     26        /// Generates assignment operators, constructors, and destructor for aggregate types as required
     27        void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2828
    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
     29        /// returns true if obj's name is the empty string and it has a bitfield width
     30        bool isUnnamedBitfield( ObjectDecl * obj );
    3131
    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" );
     32        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     33        /// such as in determining array dimension type
     34        extern Type * SizeType;
    3735
    38     // for a flexible array member nothing is done -- user must define own assignment
    39     if ( ! array->get_dimension() ) return;
     36        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     37        template< typename OutputIterator >
     38        void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward = true );
    4039
    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( "--?" );
     40        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     41        template< typename OutputIterator >
     42        void genScalarCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out ) {
     43                // want to be able to generate assignment, ctor, and dtor generically,
     44                // so fname is either ?=?, ?{}, or ^?{}
     45                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     46
     47                // do something special for unnamed members
     48                fExpr->get_args().push_back( new AddressExpr( dstParam ) );
     49
     50                if ( srcParam ) {
     51                        fExpr->get_args().push_back( srcParam );
     52                }
     53
     54                *out++ = new ExprStmt( noLabels, fExpr );
     55        }
     56
     57        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     58        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     59        template< typename OutputIterator >
     60        void genArrayCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool forward = true ) {
     61                static UniqueName indexName( "_index" );
     62
     63                // for a flexible array member nothing is done -- user must define own assignment
     64                if ( ! array->get_dimension() ) return ;
     65
     66                Expression * begin, * end, * update, * cmp;
     67                if ( forward ) {
     68                        // generate: for ( int i = 0; i < 0; ++i )
     69                        begin = new NameExpr( "0" );
     70                        end = array->get_dimension()->clone();
     71                        cmp = new NameExpr( "?<?" );
     72                        update = new NameExpr( "++?" );
     73                } else {
     74                        // generate: for ( int i = N-1; i >= 0; --i )
     75                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
     76                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     77                        ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
     78                        end = new NameExpr( "0" );
     79                        cmp = new NameExpr( "?>=?" );
     80                        update = new NameExpr( "--?" );
     81                }
     82
     83                ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     84
     85                UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     86                init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     87                init->get_args().push_back( begin );
     88                index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     89
     90                UntypedExpr *cond = new UntypedExpr( cmp );
     91                cond->get_args().push_back( new VariableExpr( index ) );
     92                cond->get_args().push_back( end );
     93
     94                UntypedExpr *inc = new UntypedExpr( update );
     95                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     96
     97                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     98                dstIndex->get_args().push_back( dstParam );
     99                dstIndex->get_args().push_back( new VariableExpr( index ) );
     100                dstParam = dstIndex;
     101
     102                // srcParam is NULL for default ctor/dtor
     103                if ( srcParam ) {
     104                        UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     105                        srcIndex->get_args().push_back( srcParam );
     106                        srcIndex->get_args().push_back( new VariableExpr( index ) );
     107                        srcParam = srcIndex;
     108                }
     109
     110                // for stmt's body, eventually containing call
     111                CompoundStmt * body = new CompoundStmt( noLabels );
     112                genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), forward );
     113
     114                // block containing for stmt and index variable
     115                std::list<Statement *> initList;
     116                CompoundStmt * block = new CompoundStmt( noLabels );
     117                block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     118                block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     119
     120                *out++ = block;
     121        }
     122
     123        template< typename OutputIterator >
     124        void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward ) {
     125                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     126                        genArrayCall( srcParam, dstParam, fname, out, at, forward );
     127                } else {
     128                        genScalarCall( srcParam, dstParam, fname, out );
     129                }
     130        }
     131
     132        /// inserts into out a generated call expression to function fname with arguments dstParam
     133        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     134        /// object being constructed. The function wraps constructor and destructor calls in an
     135        /// ImplicitCtorDtorStmt node.
     136        template< typename OutputIterator >
     137        void genImplicitCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     138                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     139                assert( obj );
     140                // unnamed bit fields are not copied as they cannot be accessed
     141                if ( isUnnamedBitfield( obj ) ) return;
     142
     143                std::list< Statement * > stmts;
     144                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward );
     145
     146                // 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
     147                assert( stmts.size() <= 1 );
     148    if ( stmts.size() == 1 ) {
     149                Statement * callStmt = stmts.front();
     150                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
     151                        // implicitly generated ctor/dtor calls should be wrapped
     152                        // so that later passes are aware they were generated.
     153                        // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     154                        // because this causes the address to be taken at codegen, which is illegal in C.
     155                        callStmt = new ImplicitCtorDtorStmt( callStmt );
     156                }
     157                *out++ = callStmt;
    56158    }
    57 
    58     ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    59 
    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*>() ) );
    64 
    65     UntypedExpr *cond = new UntypedExpr( cmp );
    66     cond->get_args().push_back( new VariableExpr( index ) );
    67     cond->get_args().push_back( end );
    68 
    69     UntypedExpr *inc = new UntypedExpr( update );
    70     inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    71 
    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 ) );
    75 
    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 );
    80 
    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 );
    87     }
    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   }
     159        }
    102160} // namespace SymTab
    103161#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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/main.cc

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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

    re4957e7 r29e8bf5  
    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.