Changes in / [29e8bf5:e4957e7]


Ignore:
Location:
src
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/DeclMutator.h

    r29e8bf5 re4957e7  
    2828        class DeclMutator : public Mutator {
    2929        public:
    30                 typedef Mutator Parent;
    31 
    3230                DeclMutator();
    3331                virtual ~DeclMutator();
    34 
    35                 using Parent::mutate;
     32               
    3633                virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
    3734                virtual Statement* mutate(IfStmt *ifStmt);
     
    4542                /// Mutates a list of declarations with this visitor
    4643                void mutateDeclarationList(std::list< Declaration* >& decls);
    47 
     44               
    4845                /// Called on entry to a new scope; overriders should call this as a super-class call
    4946                virtual void doBeginScope();
  • src/GenPoly/Specialize.cc

    r29e8bf5 re4957e7  
    3131#include "Common/UniqueName.h"
    3232#include "Common/utility.h"
    33 #include "InitTweak/InitTweak.h"
    3433
    3534namespace GenPoly {
     
    185184                mutateAll( appExpr->get_args(), *this );
    186185
    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                 }
     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 );
    196192
    197193                return appExpr;
  • src/InitTweak/FixGlobalInit.cc

    r29e8bf5 re4957e7  
    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        }
    4891
    4992        void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
     
    97140                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    98141
     142                if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
     143                if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    99144                // C allows you to initialize objects with constant expressions
    100145                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    102147                // if ( isConstExpr( objDecl->get_init() ) ) return;
    103148
    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() );
     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 ) );
    107156
    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;
     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 ) ) );
    127167                } // if
    128168        }
  • src/InitTweak/FixInit.cc

    r29e8bf5 re4957e7  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "FixInit.h"
    2021#include "InitTweak.h"
    21 #include "FixInit.h"
    22 #include "FixGlobalInit.h"
    2322#include "ResolvExpr/Resolver.h"
    2423#include "ResolvExpr/typeops.h"
     
    8483                };
    8584
    86                 // debug
    8785                struct printSet {
    8886                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    161159
    162160                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    163 
    164                         std::list< Declaration * > staticDtorDecls;
    165161                };
    166162
     
    175171        } // namespace
    176172
    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 
     173        void fix( std::list< Declaration * > & translationUnit ) {
    181174                InsertImplicitCalls::insert( translationUnit );
    182175                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    201194                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    202195                        FixInit 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
     196                        mutateAll( translationUnit, fixer );
    220197                }
    221198
     
    445422                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    446423                                        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                                                 //
    452424                                                // generate:
    453                                                 // T * __objName_static_ptrN;
    454                                                 // void __objName_dtor_atexitN() {
    455                                                 //   __dtor(__objName_static_ptrN);
     425                                                // static bool __objName_uninitialized = true;
     426                                                // if (__objName_uninitialized) {
     427                                                //   __ctor(__objName);
     428                                                //   void dtor_atexit() {
     429                                                //     __dtor(__objName);
     430                                                //   }
     431                                                //   on_exit(dtorOnExit, &__objName);
     432                                                //   __objName_uninitialized = false;
    456433                                                // }
    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;
    466                                                 //   }
    467                                                 //   ...
    468                                                 // }
    469 
    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
     434
     435                                                // generate first line
    490436                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    491437                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    493439                                                isUninitializedVar->fixUniqueId();
    494440
    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);
     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);
    501447                                                UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    502448                                                callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     
    511457                                                std::list< Statement * > & body = initStmts->get_kids();
    512458                                                body.push_back( ctor );
    513                                                 body.push_back( new ExprStmt( noLabels, ptrAssign ) );
     459                                                body.push_back( new DeclStmt( noLabels, dtorCaller ) );
    514460                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    515461                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
     
    519465                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    520466                                                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 );
    525467                                        } else {
    526468                                                stmtsToAddAfter.push_back( ctor );
  • src/InitTweak/FixInit.h

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

    r29e8bf5 re4957e7  
    2626#include "SymTab/Autogen.h"
    2727#include "GenPoly/PolyMutator.h"
    28 #include "GenPoly/DeclMutator.h"
    2928
    3029namespace InitTweak {
     
    5655          public:
    5756                /// create constructor and destructor statements for object declarations.
    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.
     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
    6160                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
     61
     62                CtorDtor() : inFunction( false ) {}
    6263
    6364                virtual DeclarationWithType * mutate( ObjectDecl * );
    6465                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    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; }
     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 );
    7574
    7675          protected:
    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;
     76                bool inFunction;
    10677        };
    10778
    10879        void genInit( std::list< Declaration * > & translationUnit ) {
    10980                ReturnFixer::makeReturnTemp( translationUnit );
    110                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    11181                CtorDtor::generateCtorDtor( translationUnit );
    11282        }
     
    154124        }
    155125
    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         }
    199126
    200127        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    213140
    214141        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    215                 // hands off if designated, if @=, or if extern
     142                // hands off if designated or if @=
    216143                if ( tryConstruct( objDecl ) ) {
    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() ) );
     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() ) );
    243166                                                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.
    244175                                        }
    245176                                } else {
    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 
     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() ) );
    254187                                }
    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() ) );
    266188                        }
    267189                }
     
    271193        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    272194                // parameters should not be constructed and destructed, so don't mutate FunctionType
     195                bool oldInFunc = inFunction;
    273196                mutateAll( functionDecl->get_oldDecls(), *this );
     197                inFunction = true;
    274198                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     199                inFunction = oldInFunc;
    275200                return functionDecl;
    276201        }
     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
    277213} // namespace InitTweak
    278214
  • src/InitTweak/InitTweak.cc

    r29e8bf5 re4957e7  
    5757                        (objDecl->get_init() == NULL ||
    5858                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() )
    60                         && objDecl->get_storageClass() != DeclarationNode::Extern;
     59                        ! isDesignated( objDecl->get_init() );
    6160        }
    6261
     
    8584                }
    8685        }
    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         }
    10386
    10487        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    10588                Expression * callExpr = getCtorDtorCall( stmt );
    10689                if ( ! callExpr ) return false;
    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;
     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;
    11499        }
    115100
     
    175160                else return NULL;
    176161        }
    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 
    230162}
  • src/InitTweak/InitTweak.h

    r29e8bf5 re4957e7  
    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   /// Non-Null if expr is a call expression whose target function is intrinsic
    38   ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
     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 );
    3941
    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 );
     42  /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     43  Expression * getCtorDtorCall( Statement * stmt );
    4444
    45         /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    46         Expression * getCtorDtorCall( Statement * stmt );
     45  /// returns the name of the function being called
     46  std::string getFunctionName( Expression * expr );
    4747
    48         /// returns the name of the function being called
    49         std::string getFunctionName( Expression * expr );
     48  /// returns the argument to a call expression in position N indexed from 0
     49  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    5050
    51         /// returns the argument to a call expression in position N indexed from 0
    52         Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     51  /// returns the base type of a PointerType or ArrayType, else returns NULL
     52  Type * getPointerBase( Type * );
    5353
    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 );
     54  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     55  Type * isPointerType( Type * );
    6356} // namespace
    6457
  • src/ResolvExpr/Resolver.cc

    r29e8bf5 re4957e7  
    2424#include "SynTree/Initializer.h"
    2525#include "SymTab/Indexer.h"
    26 #include "SymTab/Autogen.h"
    2726#include "Common/utility.h"
    2827#include "InitTweak/InitTweak.h"
     
    4241
    4342                virtual void visit( ArrayType * at );
    44                 virtual void visit( PointerType * at );
    4543
    4644                virtual void visit( ExprStmt *exprStmt );
     
    6159          private:
    6260        typedef std::list< Initializer * >::iterator InitIterator;
    63 
    64                 template< typename PtrType >
    65                 void handlePtrType( PtrType * type );
    6661
    6762          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    197192        }
    198193
    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() );
     194        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() );
    203198                        Expression *newExpr = findSingleExpression( castExpr, *this );
    204                         delete type->get_dimension();
    205                         type->set_dimension( newExpr );
    206                 }
    207         }
    208 
    209         void Resolver::visit( ArrayType * at ) {
    210                 handlePtrType( at );
     199                        delete at->get_dimension();
     200                        at->set_dimension( newExpr );
     201                }
    211202                Visitor::visit( at );
    212         }
    213 
    214         void Resolver::visit( PointerType * pt ) {
    215                 handlePtrType( pt );
    216                 Visitor::visit( pt );
    217203        }
    218204
     
    551537                assert( callExpr );
    552538                Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
    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 
     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                }
    574559                // cast to T* with qualifiers removed.
    575560                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     
    577562                // remove lvalue as a qualifier, this can change to
    578563                //   type->get_qualifiers() = Type::Qualifiers();
    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 );
     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 );
    583569                constructee = new CastExpr( constructee, type );
    584570
  • src/SymTab/Autogen.cc

    r29e8bf5 re4957e7  
    2626
    2727namespace SymTab {
    28         Type * SizeType = 0;
    29 
    3028        class AutogenerateRoutines : public Visitor {
    3129                public:
     
    6159        bool isUnnamedBitfield( ObjectDecl * obj ) {
    6260                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;
    6393        }
    6494
     
    190220
    191221                // assign to destination (and return value if generic)
    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 );
     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() ) );
    202238                } // if
    203239        }
  • src/SymTab/Autogen.h

    r29e8bf5 re4957e7  
    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         /// returns true if obj's name is the empty string and it has a bitfield width
    30         bool isUnnamedBitfield( ObjectDecl * obj );
     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
    3131
    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;
     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" );
    3537
    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 );
     38    // for a flexible array member nothing is done -- user must define own assignment
     39    if ( ! array->get_dimension() ) return;
    3940
    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 ) );
     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( "--?" );
     56    }
    4657
    47                 // do something special for unnamed members
    48                 fExpr->get_args().push_back( new AddressExpr( dstParam ) );
     58    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    4959
    50                 if ( srcParam ) {
    51                         fExpr->get_args().push_back( srcParam );
    52                 }
     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*>() ) );
    5364
    54                 *out++ = new ExprStmt( noLabels, fExpr );
    55         }
     65    UntypedExpr *cond = new UntypedExpr( cmp );
     66    cond->get_args().push_back( new VariableExpr( index ) );
     67    cond->get_args().push_back( end );
    5668
    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" );
     69    UntypedExpr *inc = new UntypedExpr( update );
     70    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    6271
    63                 // for a flexible array member nothing is done -- user must define own assignment
    64                 if ( ! array->get_dimension() ) return ;
     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 ) );
    6575
    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                 }
     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 );
    8280
    83                 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     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    }
    8488
    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    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 ) ) );
    8993
    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;
     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 );
    15899    }
    159         }
     100    *out++ = stmt;
     101  }
    160102} // namespace SymTab
    161103#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

    r29e8bf5 re4957e7  
    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                 // 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() );
     46                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
    4847                delete arrayType;
    4948                return pointerType;
  • src/SymTab/Validate.cc

    r29e8bf5 re4957e7  
    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
    194193                acceptAll( translationUnit, pass1 );
    195194                acceptAll( translationUnit, pass2 );
    196195                ReturnChecker::checkFunctionReturns( translationUnit );
    197                 compoundliteral.mutateDeclarationList( translationUnit );
     196                mutateAll( translationUnit, compoundliteral );
     197                autogenerateRoutines( 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                 }
    500492                filter( translationUnit, isTypedef, true );
    501 
    502493        }
    503494
     
    527518        Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
    528519                Declaration *ret = Mutator::mutate( tyDecl );
    529 
    530520                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    531521                        // typedef to the same name from the same scope
  • src/main.cc

    r29e8bf5 re4957e7  
    4242#include "InitTweak/GenInit.h"
    4343#include "InitTweak/FixInit.h"
     44#include "InitTweak/FixGlobalInit.h"
    4445//#include "Explain/GenProlog.h"
    4546//#include "Try/Visit.h"
     
    281282                OPTPRINT( "fixNames" )
    282283                CodeGen::fixNames( translationUnit );
     284                OPTPRINT( "fixGlobalInit" );
     285                InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
    283286                OPTPRINT( "tweakInit" )
    284287                InitTweak::genInit( translationUnit );
     
    301304                }
    302305
     306                OPTPRINT( "fixInit" )
    303307                // fix ObjectDecl - replaces ConstructorInit nodes
    304                 OPTPRINT( "fixInit" )
    305                 InitTweak::fix( translationUnit, filename, libcfap || treep );
     308                InitTweak::fix( translationUnit );
    306309                if ( ctorinitp ) {
    307310                        dump ( translationUnit );
  • src/tests/.expect/64/extension.txt

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

    r29e8bf5 re4957e7  
    9292init_once y = x;
    9393
    94 void static_variable() {
    95         static init_once x;
    96 }
    97 
    9894int main() {
    9995        // local variables
     
    183179                }
    184180        }
    185 
    186         // function-scoped static variable
    187         for (int i = 0; i < 10; i++) {
    188                 static_variable();
    189         }
    190181}
    191182
Note: See TracChangeset for help on using the changeset viewer.