Changes in / [1b0020a:dae881f]


Ignore:
Location:
src
Files:
2 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r1b0020a rdae881f  
    148148        void CodeGenerator::visit( ObjectDecl * objectDecl ) {
    149149                extension( objectDecl );
    150                 genAttributes( objectDecl->get_attributes() );
    151 
    152150                handleStorageClass( objectDecl );
    153151                output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
     
    273271                printDesignators( init->get_designators() );
    274272                output << "{ ";
    275                 if ( init->begin() == init->end() ) {
     273                if ( init->begin_initializers() == init->end_initializers() ) {
    276274                        // illegal to leave initializer list empty for scalar initializers, but always legal to have 0
    277275                        output << "0";
    278276                } else {
    279                         genCommaList( init->begin(), init->end() );
     277                        genCommaList( init->begin_initializers(), init->end_initializers() );
    280278                } // if
    281279                output << " }";
  • src/GenPoly/DeclMutator.h

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

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

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

    r1b0020a rdae881f  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "FixInit.h"
    2021#include "InitTweak.h"
    21 #include "FixInit.h"
    22 #include "FixGlobalInit.h"
    2322#include "ResolvExpr/Resolver.h"
    2423#include "ResolvExpr/typeops.h"
     
    2625#include "SynTree/Type.h"
    2726#include "SynTree/Expression.h"
    28 #include "SynTree/Attribute.h"
    2927#include "SynTree/Statement.h"
    3028#include "SynTree/Initializer.h"
     
    8583                };
    8684
    87                 // debug
    8885                struct printSet {
    8986                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    162159
    163160                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    164 
    165                         std::list< Declaration * > staticDtorDecls;
    166161                };
    167162
     
    176171        } // namespace
    177172
    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 
     173        void fix( std::list< Declaration * > & translationUnit ) {
    182174                InsertImplicitCalls::insert( translationUnit );
    183175                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    202194                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    203195                        FixInit 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
     196                        mutateAll( translationUnit, fixer );
    219197                }
    220198
     
    444422                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    445423                                        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                                                 //
    450424                                                // generate:
    451                                                 // static T __objName_static_varN;
    452                                                 // void __objName_dtor_atexitN() {
    453                                                 //   __dtor__...;
     425                                                // static bool __objName_uninitialized = true;
     426                                                // if (__objName_uninitialized) {
     427                                                //   __ctor(__objName);
     428                                                //   void dtor_atexit() {
     429                                                //     __dtor(__objName);
     430                                                //   }
     431                                                //   on_exit(dtorOnExit, &__objName);
     432                                                //   __objName_uninitialized = false;
    454433                                                // }
    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);
    462                                                 //   }
    463                                                 //   ...
    464                                                 // }
    465 
    466                                                 static UniqueName dtorCallerNamer( "_dtor_atexit" );
    467 
    468                                                 // static bool __objName_uninitialized = true
     434
     435                                                // generate first line
    469436                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    470437                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    472439                                                isUninitializedVar->fixUniqueId();
    473440
     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
    474450                                                // __objName_uninitialized = false;
    475451                                                UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
     
    481457                                                std::list< Statement * > & body = initStmts->get_kids();
    482458                                                body.push_back( ctor );
     459                                                body.push_back( new DeclStmt( noLabels, dtorCaller ) );
     460                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    483461                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
    484462
     
    487465                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    488466                                                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                                                 }
    528467                                        } else {
    529468                                                stmtsToAddAfter.push_back( ctor );
     
    585524                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    586525                                        Statement * dtor = ctorInit->get_dtor();
    587                                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     526                                        if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
    588527                                                // don't need to call intrinsic dtor, because it does nothing, but
    589528                                                // non-intrinsic dtors must be called
  • src/InitTweak/FixInit.h

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

    r1b0020a rdae881f  
    2626#include "SymTab/Autogen.h"
    2727#include "GenPoly/PolyMutator.h"
    28 #include "GenPoly/DeclMutator.h"
    2928
    3029namespace InitTweak {
     
    5655          public:
    5756                /// create constructor and destructor statements for object declarations.
    58                 /// the actual call statements will be added in after the resolver has run
    59                 /// so that the initializer expression is only removed if a constructor is found
    60                 /// and the same destructor call is inserted in all of the appropriate locations.
     57                /// Destructors are inserted directly into the code, whereas constructors
     58                /// will be added in after the resolver has run so that the initializer expression
     59                /// is only removed if a constructor is found
    6160                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
     61
     62                CtorDtor() : inFunction( false ) {}
    6263
    6364                virtual DeclarationWithType * mutate( ObjectDecl * );
    6465                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    65                 // should not traverse into any of these declarations to find objects
    66                 // that need to be constructed or destructed
    67                 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
    68                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    69                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
    70                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
    71                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
    72                 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
    73 
    74                 virtual Type * mutate( FunctionType *funcType ) { return funcType; }
     66                virtual Declaration* mutate( StructDecl *aggregateDecl );
     67                virtual Declaration* mutate( UnionDecl *aggregateDecl );
     68                virtual Declaration* mutate( EnumDecl *aggregateDecl );
     69                virtual Declaration* mutate( TraitDecl *aggregateDecl );
     70                virtual TypeDecl* mutate( TypeDecl *typeDecl );
     71                virtual Declaration* mutate( TypedefDecl *typeDecl );
     72
     73                virtual Type * mutate( FunctionType *funcType );
    7574
    7675          protected:
    77         };
    78 
    79         class HoistArrayDimension : public GenPoly::DeclMutator {
    80           public:
    81                 typedef GenPoly::DeclMutator Parent;
    82 
    83                 /// hoist dimension from array types in object declaration so that it uses a single
    84                 /// const variable of type size_t, so that side effecting array dimensions are only
    85                 /// computed once.
    86                 static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    87 
    88           private:
    89                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl );
    90                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    91                 // should not traverse into any of these declarations to find objects
    92                 // that need to be constructed or destructed
    93                 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
    94                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    95                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
    96                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
    97                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
    98                 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
    99 
    100                 virtual Type* mutate( FunctionType *funcType ) { return funcType; }
    101 
    102                 void hoist( Type * type );
    103 
    104                 DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass;
    105                 bool inFunction = false;
     76                bool inFunction;
    10677        };
    10778
    10879        void genInit( std::list< Declaration * > & translationUnit ) {
    10980                ReturnFixer::makeReturnTemp( translationUnit );
    110                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    11181                CtorDtor::generateCtorDtor( translationUnit );
    11282        }
     
    154124        }
    155125
    156         // 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         }
    205126
    206127        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    209130        }
    210131
     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
    211141        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    212                 // hands off if designated, if @=, or if extern
     142                // hands off if designated or if @=
    213143                if ( tryConstruct( objDecl ) ) {
    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() ) );
     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                                }
    241188                        }
    242189                }
     
    246193        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    247194                // parameters should not be constructed and destructed, so don't mutate FunctionType
     195                bool oldInFunc = inFunction;
    248196                mutateAll( functionDecl->get_oldDecls(), *this );
     197                inFunction = true;
    249198                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     199                inFunction = oldInFunc;
    250200                return functionDecl;
    251201        }
     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
    252213} // namespace InitTweak
    253214
  • src/InitTweak/InitTweak.cc

    r1b0020a rdae881f  
    1 #include <algorithm>
    21#include "InitTweak.h"
    32#include "SynTree/Visitor.h"
     
    54#include "SynTree/Initializer.h"
    65#include "SynTree/Expression.h"
    7 #include "SynTree/Attribute.h"
    86#include "GenPoly/GenPoly.h"
    97
     
    2220                };
    2321
    24                 class InitFlattener : public Visitor {
     22                class InitExpander : public Visitor {
    2523                        public:
     24                        InitExpander() {}
    2625                        virtual void visit( SingleInit * singleInit );
    2726                        virtual void visit( ListInit * listInit );
     
    2928                };
    3029
    31                 void InitFlattener::visit( SingleInit * singleInit ) {
     30                void InitExpander::visit( SingleInit * singleInit ) {
    3231                        argList.push_back( singleInit->get_value()->clone() );
    3332                }
    3433
    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 ) {
     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 ) {
    3938                                (*it)->accept( *this );
    4039                        }
     
    4342
    4443        std::list< Expression * > makeInitList( Initializer * init ) {
    45                 InitFlattener flattener;
    46                 maybeAccept( init, flattener );
    47                 return flattener.argList;
     44                InitExpander expander;
     45                maybeAccept( init, expander );
     46                return expander.argList;
    4847        }
    4948
     
    5453        }
    5554
    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 
    22755        bool tryConstruct( ObjectDecl * objDecl ) {
    22856                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    22957                        (objDecl->get_init() == NULL ||
    23058                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    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 );
     59                        ! isDesignated( objDecl->get_init() );
    26660        }
    26761
    26862        Expression * getCtorDtorCall( Statement * stmt ) {
    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() );
     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" );
    28084                }
    28185        }
    28286
    283         ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    284                 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    285                 if ( ! appExpr ) return NULL;
    286                 VariableExpr * function = getCalledFunction( appExpr );
     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() );
    28793                assert( function );
    28894                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    28995                // will call all member dtors, and some members may have a user defined dtor.
    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                 });
     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;
    30699        }
    307100
     
    367160                else return NULL;
    368161        }
    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 
    422162}
  • src/InitTweak/InitTweak.h

    r1b0020a rdae881f  
    2626// helper functions for initialization
    2727namespace InitTweak {
    28         /// transform Initializer into an argument list that can be passed to a call expression
    29         std::list< Expression * > makeInitList( Initializer * init );
     28  /// transform Initializer into an argument list that can be passed to a call expression
     29  std::list< Expression * > makeInitList( Initializer * init );
    3030
    31         /// True if the resolver should try to construct objDecl
    32         bool tryConstruct( ObjectDecl * objDecl );
     31  /// True if the resolver should try to construct objDecl
     32  bool tryConstruct( ObjectDecl * objDecl );
    3333
    34         /// True if the Initializer contains designations
    35         bool isDesignated( Initializer * init );
     34  /// True if the Initializer contains designations
     35  bool isDesignated( Initializer * init );
    3636
    37   /// Non-Null if expr is a call expression whose target function is intrinsic
    38   ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
     37  /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     38  /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
     39  /// Currently has assertions that make it less than fully general.
     40  bool isInstrinsicSingleArgCallStmt( Statement * expr );
    3941
    40         /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
    41         /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
    42         /// Currently has assertions that make it less than fully general.
    43         bool isIntrinsicSingleArgCallStmt( Statement * expr );
     42  /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     43  Expression * getCtorDtorCall( Statement * stmt );
    4444
    45         /// get all Ctor/Dtor call expressions from a Statement
    46         void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
     45  /// returns the name of the function being called
     46  std::string getFunctionName( Expression * expr );
    4747
    48         /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    49         Expression * getCtorDtorCall( Statement * stmt );
     48  /// returns the argument to a call expression in position N indexed from 0
     49  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    5050
    51         /// returns the name of the function being called
    52         std::string getFunctionName( Expression * expr );
     51  /// returns the base type of a PointerType or ArrayType, else returns NULL
     52  Type * getPointerBase( Type * );
    5353
    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         };
     54  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     55  Type * isPointerType( Type * );
    9456} // namespace
    9557
  • src/Parser/TypeData.cc

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

    r1b0020a rdae881f  
    2424#include "SynTree/Initializer.h"
    2525#include "SymTab/Indexer.h"
    26 #include "SymTab/Autogen.h"
    2726#include "Common/utility.h"
    2827#include "InitTweak/InitTweak.h"
     
    4241
    4342                virtual void visit( ArrayType * at );
    44                 virtual void visit( PointerType * at );
    4543
    4644                virtual void visit( ExprStmt *exprStmt );
     
    5452                virtual void visit( BranchStmt *branchStmt );
    5553                virtual void visit( ReturnStmt *returnStmt );
     54                virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5655
    5756                virtual void visit( SingleInit *singleInit );
     
    6059          private:
    6160        typedef std::list< Initializer * >::iterator InitIterator;
    62 
    63                 template< typename PtrType >
    64                 void handlePtrType( PtrType * type );
    6561
    6662          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    196192        }
    197193
    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() );
     194        void Resolver::visit( ArrayType * at ) {
     195                if ( at->get_dimension() ) {
     196                        BasicType arrayLenType = BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     197                        CastExpr *castExpr = new CastExpr( at->get_dimension(), arrayLenType.clone() );
    202198                        Expression *newExpr = findSingleExpression( castExpr, *this );
    203                         delete type->get_dimension();
    204                         type->set_dimension( newExpr );
    205                 }
    206         }
    207 
    208         void Resolver::visit( ArrayType * at ) {
    209                 handlePtrType( at );
     199                        delete at->get_dimension();
     200                        at->set_dimension( newExpr );
     201                }
    210202                Visitor::visit( at );
    211         }
    212 
    213         void Resolver::visit( PointerType * pt ) {
    214                 handlePtrType( pt );
    215                 Visitor::visit( pt );
    216203        }
    217204
     
    435422
    436423        void Resolver::visit( ListInit * listInit ) {
    437                 InitIterator iter = listInit->begin();
    438                 InitIterator end = listInit->end();
     424                InitIterator iter = listInit->begin_initializers();
     425                InitIterator end = listInit->end_initializers();
    439426
    440427                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     
    534521                // implicitly generated, there's no way for it to have side effects, so get rid of it
    535522                // to clean up generated code.
    536                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
     523                if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    537524                        delete ctorInit->get_ctor();
    538525                        ctorInit->set_ctor( NULL );
    539526                }
    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() ) ) {
     527                if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    548528                        delete ctorInit->get_dtor();
    549529                        ctorInit->set_dtor( NULL );
    550530                }
     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 );
    551573        }
    552574} // namespace ResolvExpr
  • src/SymTab/Autogen.cc

    r1b0020a rdae881f  
    2626
    2727namespace SymTab {
    28         Type * SizeType = 0;
    29 
    3028        class AutogenerateRoutines : public Visitor {
    3129                public:
     
    6159        bool isUnnamedBitfield( ObjectDecl * obj ) {
    6260                return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
     61        }
     62
     63        template< typename OutputIterator >
     64        void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
     65                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
     66                // unnamed bit fields are not copied as they cannot be accessed
     67                if ( isUnnamedBitfield( obj ) ) return;
     68
     69                // want to be able to generate assignment, ctor, and dtor generically,
     70                // so fname is either ?=?, ?{}, or ^?{}
     71                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     72
     73                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     74                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     75
     76                // do something special for unnamed members
     77                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
     78                fExpr->get_args().push_back( dstselect );
     79
     80                if ( src ) {
     81                        fExpr->get_args().push_back( src );
     82                }
     83
     84                Statement * callStmt = new ExprStmt( noLabels, fExpr );
     85                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
     86                        // implicitly generated ctor/dtor calls should be wrapped
     87                        // so that later passes are aware they were generated.
     88                        // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     89                        // because this causes the address to be taken at codegen, which is illegal in C.
     90                        callStmt = new ImplicitCtorDtorStmt( callStmt );
     91                }
     92                *out++ = callStmt;
    6393        }
    6494
     
    189219                }
    190220
    191                 InitTweak::InitExpander srcParam( src );
    192 
    193221                // assign to destination (and return value if generic)
    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 );
     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() ) );
    204238                } // if
    205239        }
  • src/SymTab/Autogen.h

    r1b0020a rdae881f  
    2222#include "SynTree/Declaration.h"
    2323#include "SynTree/Initializer.h"
    24 #include "InitTweak/InitTweak.h"
    2524
    2625namespace SymTab {
    27         /// Generates assignment operators, constructors, and destructor for aggregate types as required
    28         void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     26  /// Generates assignment operators, constructors, and destructor for aggregate types as required
     27  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2928
    30         /// returns true if obj's name is the empty string and it has a bitfield width
    31         bool isUnnamedBitfield( ObjectDecl * obj );
     29  // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
     30  // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
    3231
    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;
     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" );
    3637
    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 );
     38    // for a flexible array member nothing is done -- user must define own assignment
     39    if ( ! array->get_dimension() ) return;
    4040
    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 ) );
     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    }
    4857
    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 );
     58    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    6559
    66                 Statement * listInit = srcParam.buildListInit( fExpr );
     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*>() ) );
    6764
    68                 std::list< Expression * > args = *++srcParam;
    69                 fExpr->get_args().splice( fExpr->get_args().end(), args );
     65    UntypedExpr *cond = new UntypedExpr( cmp );
     66    cond->get_args().push_back( new VariableExpr( index ) );
     67    cond->get_args().push_back( end );
    7068
    71                 *out++ = new ExprStmt( noLabels, fExpr );
     69    UntypedExpr *inc = new UntypedExpr( update );
     70    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    7271
    73                 srcParam.clearArrayIndices();
     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 ) );
    7475
    75                 return listInit;
    76         }
     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 );
    7780
    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" );
     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    }
    8388
    84                 // for a flexible array member nothing is done -- user must define own assignment
    85                 if ( ! array->get_dimension() ) return ;
     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 ) ) );
    8693
    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         }
     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  }
    180102} // namespace SymTab
    181103#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

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

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

    r1b0020a rdae881f  
    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"
    2322#include "Common/utility.h"
    2423
  • src/SynTree/Declaration.h

    r1b0020a rdae881f  
    6464class DeclarationWithType : public Declaration {
    6565  public:
    66         DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes );
     66        DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage );
    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; }
    8077
    8178        virtual DeclarationWithType *clone() const = 0;
     
    9087        // shadowed identifiers can be accessed
    9188        int scopeLevel = 0;
    92 
    93         std::list< Attribute * > attributes;
    9489};
    9590
     
    9792        typedef DeclarationWithType Parent;
    9893  public:
    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 );
     94        ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline = false, bool isNoreturn = false );
    10095        ObjectDecl( const ObjectDecl &other );
    10196        virtual ~ObjectDecl();
     
    136131        std::list< std::string >& get_oldIdents() { return oldIdents; }
    137132        std::list< Declaration* >& get_oldDecls() { return oldDecls; }
     133        std::list< Attribute * >& get_attributes() { return attributes; }
    138134
    139135        virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
     
    147143        std::list< std::string > oldIdents;
    148144        std::list< Declaration* > oldDecls;
     145        std::list< Attribute * > attributes;
    149146};
    150147
  • src/SynTree/DeclarationWithType.cc

    r1b0020a rdae881f  
    1616#include "Declaration.h"
    1717#include "Type.h"
    18 #include "Attribute.h"
    1918#include "Common/utility.h"
    2019
    21 DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes )
    22                 : Declaration( name, sc, linkage ), attributes( attributes ) {
     20DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage )
     21                : Declaration( name, sc, linkage ) {
    2322}
    2423
    2524DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
    2625                : Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) {
    27         cloneAll( other.attributes, attributes );
    2826}
    2927
    3028DeclarationWithType::~DeclarationWithType() {
    31         deleteAll( attributes );
    3229}
    3330
  • src/SynTree/Expression.cc

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

    r1b0020a rdae881f  
    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, attributes ), type( type ), statements( statements ) {
     25                : Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) {
    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 );
    3637}
    3738
     
    3940        delete type;
    4041        delete statements;
     42        deleteAll( attributes );
    4143}
    4244
     
    6769        } // if
    6870
    69         printAll( get_attributes(), os, indent );
     71        printAll( attributes, os, indent );
    7072
    7173        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
  • src/SynTree/Initializer.h

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

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

    r1b0020a rdae881f  
    1818#include "Initializer.h"
    1919#include "Expression.h"
    20 #include "Attribute.h"
    2120#include "Common/utility.h"
    2221#include "Statement.h"
    2322
    24 ObjectDecl::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 ) {
     23ObjectDecl::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 ) {
    2625        set_isInline( isInline );
    2726        set_isNoreturn( isNoreturn );
     
    4645                os << LinkageSpec::toString( get_linkage() ) << " ";
    4746        } // if
    48 
    49         printAll( get_attributes(), os, indent );
    5047
    5148        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
     
    8380        } // if
    8481
    85         // xxx - should printShort print attributes?
    86 
    8782        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
    8883                os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
  • src/main.cc

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

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

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