Changes in / [dae881f:1b0020a]


Ignore:
Location:
src
Files:
2 added
26 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rdae881f r1b0020a  
    148148        void CodeGenerator::visit( ObjectDecl * objectDecl ) {
    149149                extension( objectDecl );
     150                genAttributes( objectDecl->get_attributes() );
     151
    150152                handleStorageClass( objectDecl );
    151153                output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
     
    271273                printDesignators( init->get_designators() );
    272274                output << "{ ";
    273                 if ( init->begin_initializers() == init->end_initializers() ) {
     275                if ( init->begin() == init->end() ) {
    274276                        // illegal to leave initializer list empty for scalar initializers, but always legal to have 0
    275277                        output << "0";
    276278                } else {
    277                         genCommaList( init->begin_initializers(), init->end_initializers() );
     279                        genCommaList( init->begin(), init->end() );
    278280                } // if
    279281                output << " }";
  • src/GenPoly/DeclMutator.h

    rdae881f r1b0020a  
    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

    rdae881f r1b0020a  
    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

    rdae881f r1b0020a  
    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 && ! isIntrinsicSingleArgCallStmt( 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

    rdae881f r1b0020a  
    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"
     
    2526#include "SynTree/Type.h"
    2627#include "SynTree/Expression.h"
     28#include "SynTree/Attribute.h"
    2729#include "SynTree/Statement.h"
    2830#include "SynTree/Initializer.h"
     
    8385                };
    8486
     87                // debug
    8588                struct printSet {
    8689                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    159162
    160163                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
     164
     165                        std::list< Declaration * > staticDtorDecls;
    161166                };
    162167
     
    171176        } // namespace
    172177
    173         void fix( std::list< Declaration * > & translationUnit ) {
     178        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     179                // fixes ConstructorInit for global variables. should happen before fixInitializers.
     180                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     181
    174182                InsertImplicitCalls::insert( translationUnit );
    175183                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    194202                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    195203                        FixInit fixer;
    196                         mutateAll( translationUnit, fixer );
     204
     205                        // can't use mutateAll, because need to insert declarations at top-level
     206                        // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
     207                        SemanticError errors;
     208                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     209                                try {
     210                                        *i = maybeMutate( *i, fixer );
     211                                        translationUnit.splice( i, fixer.staticDtorDecls );
     212                                } catch( SemanticError &e ) {
     213                                        errors.append( e );
     214                                } // try
     215                        } // for
     216                        if ( ! errors.isEmpty() ) {
     217                                throw errors;
     218                        } // if
    197219                }
    198220
     
    422444                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    423445                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
     446                                                // originally wanted to take advantage of gcc nested functions, but
     447                                                // we get memory errors with this approach. To remedy this, the static
     448                                                // variable is hoisted when the destructor needs to be called.
     449                                                //
    424450                                                // generate:
    425                                                 // static bool __objName_uninitialized = true;
    426                                                 // if (__objName_uninitialized) {
    427                                                 //   __ctor(__objName);
    428                                                 //   void dtor_atexit() {
    429                                                 //     __dtor(__objName);
     451                                                // static T __objName_static_varN;
     452                                                // void __objName_dtor_atexitN() {
     453                                                //   __dtor__...;
     454                                                // }
     455                                                // int f(...) {
     456                                                //   ...
     457                                                //   static bool __objName_uninitialized = true;
     458                                                //   if (__objName_uninitialized) {
     459                                                //     __ctor(__objName);
     460                                                //     __objName_uninitialized = false;
     461                                                //     atexit(__objName_dtor_atexitN);
    430462                                                //   }
    431                                                 //   on_exit(dtorOnExit, &__objName);
    432                                                 //   __objName_uninitialized = false;
     463                                                //   ...
    433464                                                // }
    434465
    435                                                 // generate first line
     466                                                static UniqueName dtorCallerNamer( "_dtor_atexit" );
     467
     468                                                // static bool __objName_uninitialized = true
    436469                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    437470                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    439472                                                isUninitializedVar->fixUniqueId();
    440473
    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);
    447                                                 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    448                                                 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
    449 
    450474                                                // __objName_uninitialized = false;
    451475                                                UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
     
    457481                                                std::list< Statement * > & body = initStmts->get_kids();
    458482                                                body.push_back( ctor );
    459                                                 body.push_back( new DeclStmt( noLabels, dtorCaller ) );
    460                                                 body.push_back( new ExprStmt( noLabels, callAtexit ) );
    461483                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
    462484
     
    465487                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    466488                                                stmtsToAddAfter.push_back( ifStmt );
     489
     490                                                if ( ctorInit->get_dtor() ) {
     491                                                        // if the object has a non-trivial destructor, have to
     492                                                        // hoist it and the object into the global space and
     493                                                        // call the destructor function with atexit.
     494
     495                                                        Statement * dtorStmt = ctorInit->get_dtor()->clone();
     496
     497                                                        // void __objName_dtor_atexitN(...) {...}
     498                                                        FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
     499                                                        dtorCaller->fixUniqueId();
     500                                                        dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
     501
     502                                                        // atexit(dtor_atexit);
     503                                                        UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
     504                                                        callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     505
     506                                                        body.push_back( new ExprStmt( noLabels, callAtexit ) );
     507
     508                                                        // hoist variable and dtor caller decls to list of decls that will be added into global scope
     509                                                        staticDtorDecls.push_back( objDecl );
     510                                                        staticDtorDecls.push_back( dtorCaller );
     511
     512                                                        // need to rename object uniquely since it now appears
     513                                                        // at global scope and there could be multiple function-scoped
     514                                                        // static variables with the same name in different functions.
     515                                                        static UniqueName staticNamer( "_static_var" );
     516                                                        objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
     517
     518                                                        objDecl->set_init( NULL );
     519                                                        ctorInit->set_ctor( NULL );
     520                                                        delete ctorInit;
     521
     522                                                        // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
     523                                                        // create a new object which is never used
     524                                                        static UniqueName dummyNamer( "_dummy" );
     525                                                        ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );
     526                                                        return dummy;
     527                                                }
    467528                                        } else {
    468529                                                stmtsToAddAfter.push_back( ctor );
     
    524585                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    525586                                        Statement * dtor = ctorInit->get_dtor();
    526                                         if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     587                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    527588                                                // don't need to call intrinsic dtor, because it does nothing, but
    528589                                                // non-intrinsic dtors must be called
  • src/InitTweak/FixInit.h

    rdae881f r1b0020a  
    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

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

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

    rdae881f r1b0020a  
    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 isIntrinsicSingleArgCallStmt( Statement * expr );
    4444
    45   /// returns the name of the function being called
    46   std::string getFunctionName( Expression * expr );
     45        /// get all Ctor/Dtor call expressions from a Statement
     46        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    4747
    48   /// returns the argument to a call expression in position N indexed from 0
    49   Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     48        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     49        Expression * getCtorDtorCall( Statement * stmt );
    5050
    51   /// returns the base type of a PointerType or ArrayType, else returns NULL
    52   Type * getPointerBase( Type * );
     51        /// returns the name of the function being called
     52        std::string getFunctionName( Expression * expr );
    5353
    54   /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    55   Type * isPointerType( Type * );
     54        /// returns the argument to a call expression in position N indexed from 0
     55        Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     56
     57        /// returns the base type of a PointerType or ArrayType, else returns NULL
     58        Type * getPointerBase( Type * );
     59
     60        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     61        Type * isPointerType( Type * );
     62
     63        /// returns true if expr is trivially a compile-time constant
     64        bool isConstExpr( Expression * expr );
     65        bool isConstExpr( Initializer * init );
     66
     67        class InitExpander {
     68        public:
     69                // expand by stepping through init to get each list of arguments
     70                InitExpander( Initializer * init );
     71
     72                // always expand to expr
     73                InitExpander( Expression * expr );
     74
     75                // iterator-like interface
     76                std::list< Expression * > operator*();
     77                InitExpander & operator++();
     78
     79                // builds statement which has the same semantics as a C-style list initializer
     80                // (for array initializers) using callExpr as the base expression to perform initialization
     81                Statement * buildListInit( UntypedExpr * callExpr );
     82                void addArrayIndex( Expression * index, Expression * dimension );
     83                void clearArrayIndices();
     84
     85                class ExpanderImpl;
     86        private:
     87                std::shared_ptr< ExpanderImpl > expander;
     88                std::list< Expression * > cur;
     89
     90                // invariant: list of size 2N (elements come in pairs [index, dimension])
     91                typedef std::list< Expression * > IndexList;
     92                IndexList indices;
     93        };
    5694} // namespace
    5795
  • src/Parser/TypeData.cc

    rdae881f r1b0020a  
    510510                return buildVariable();
    511511        } else {
    512                 return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, isInline, isNoreturn );
     512                return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, std::list< Attribute * >(),  isInline, isNoreturn );
    513513        } // if
    514514        return 0;
  • src/ResolvExpr/Resolver.cc

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

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

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

    rdae881f r1b0020a  
    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

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

    rdae881f r1b0020a  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Declaration.cc -- 
     7// Declaration.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2020#include "Initializer.h"
    2121#include "Type.h"
     22#include "Attribute.h"
    2223#include "Common/utility.h"
    2324
  • src/SynTree/Declaration.h

    rdae881f r1b0020a  
    6464class DeclarationWithType : public Declaration {
    6565  public:
    66         DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage );
     66        DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes );
    6767        DeclarationWithType( const DeclarationWithType &other );
    6868        virtual ~DeclarationWithType();
     
    7575        int get_scopeLevel() const { return scopeLevel; }
    7676        void set_scopeLevel( int newValue ) { scopeLevel = newValue; }
     77
     78        std::list< Attribute * >& get_attributes() { return attributes; }
     79        const std::list< Attribute * >& get_attributes() const { return attributes; }
    7780
    7881        virtual DeclarationWithType *clone() const = 0;
     
    8790        // shadowed identifiers can be accessed
    8891        int scopeLevel = 0;
     92
     93        std::list< Attribute * > attributes;
    8994};
    9095
     
    9297        typedef DeclarationWithType Parent;
    9398  public:
    94         ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline = false, bool isNoreturn = false );
     99        ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes = std::list< Attribute * >(), bool isInline = false, bool isNoreturn = false );
    95100        ObjectDecl( const ObjectDecl &other );
    96101        virtual ~ObjectDecl();
     
    131136        std::list< std::string >& get_oldIdents() { return oldIdents; }
    132137        std::list< Declaration* >& get_oldDecls() { return oldDecls; }
    133         std::list< Attribute * >& get_attributes() { return attributes; }
    134138
    135139        virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
     
    143147        std::list< std::string > oldIdents;
    144148        std::list< Declaration* > oldDecls;
    145         std::list< Attribute * > attributes;
    146149};
    147150
  • src/SynTree/DeclarationWithType.cc

    rdae881f r1b0020a  
    1616#include "Declaration.h"
    1717#include "Type.h"
     18#include "Attribute.h"
    1819#include "Common/utility.h"
    1920
    20 DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage )
    21                 : Declaration( name, sc, linkage ) {
     21DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes )
     22                : Declaration( name, sc, linkage ), attributes( attributes ) {
    2223}
    2324
    2425DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
    2526                : Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) {
     27        cloneAll( other.attributes, attributes );
    2628}
    2729
    2830DeclarationWithType::~DeclarationWithType() {
     31        deleteAll( attributes );
    2932}
    3033
  • src/SynTree/Expression.cc

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

    rdae881f r1b0020a  
    2323
    2424FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes )
    25                 : Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) {
     25                : Parent( name, sc, linkage, attributes ), type( type ), statements( statements ) {
    2626        set_isInline( isInline );
    2727        set_isNoreturn( isNoreturn );
     
    3434FunctionDecl::FunctionDecl( const FunctionDecl &other )
    3535        : Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
    36                 cloneAll( other.attributes, attributes );
    3736}
    3837
     
    4039        delete type;
    4140        delete statements;
    42         deleteAll( attributes );
    4341}
    4442
     
    6967        } // if
    7068
    71         printAll( attributes, os, indent );
     69        printAll( get_attributes(), os, indent );
    7270
    7371        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
  • src/SynTree/Initializer.h

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

    rdae881f r1b0020a  
    2424class Label {
    2525  public:
    26         Label( const std::string & name = "", Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
     26        Label( const std::string & name = "", Statement * labelled = 0, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : name( name ), labelled( labelled ), attributes( attributes ) {}
    2727        Label( const char * name, Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
    2828
  • src/SynTree/ObjectDecl.cc

    rdae881f r1b0020a  
    1818#include "Initializer.h"
    1919#include "Expression.h"
     20#include "Attribute.h"
    2021#include "Common/utility.h"
    2122#include "Statement.h"
    2223
    23 ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline, bool isNoreturn )
    24         : Parent( name, sc, linkage ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
     24ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes, bool isInline, bool isNoreturn )
     25        : Parent( name, sc, linkage, attributes ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
    2526        set_isInline( isInline );
    2627        set_isNoreturn( isNoreturn );
     
    4546                os << LinkageSpec::toString( get_linkage() ) << " ";
    4647        } // if
     48
     49        printAll( get_attributes(), os, indent );
    4750
    4851        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
     
    8083        } // if
    8184
     85        // xxx - should printShort print attributes?
     86
    8287        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
    8388                os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
  • src/main.cc

    rdae881f r1b0020a  
    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

    rdae881f r1b0020a  
    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

    rdae881f r1b0020a  
    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.