Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    r49148d5 rd56e5bc  
    2525
    2626namespace SymTab {
    27         /// Generates assignment operators, constructors, and destructor for aggregate types as required
    28         void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     27    /// Generates assignment operators, constructors, and destructor for aggregate types as required
     28    void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2929
    30         /// returns true if obj's name is the empty string and it has a bitfield width
    31         bool isUnnamedBitfield( ObjectDecl * obj );
     30    /// returns true if obj's name is the empty string and it has a bitfield width
     31    bool isUnnamedBitfield( ObjectDecl * obj );
    3232
    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;
     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;
    3636
    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 >
     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 >
    3939        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    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 >
     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 >
    4444        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 ) );
     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 ) );
    4848
    49                 if ( addCast ) {
    50                         // cast to T& with qualifiers removed, so that qualified objects can be constructed
    51                         // and destructed with the same functions as non-qualified objects.
    52                         // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    53                         // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    54                         // remove lvalue as a qualifier, this can change to
    55                         //   type->get_qualifiers() = Type::Qualifiers();
    56                         assert( type );
    57                         Type * castType = type->clone();
    58                         castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    59                         // castType->set_lvalue( true ); // xxx - might not need this
    60                         dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
    61                 }
    62                 fExpr->get_args().push_back( dstParam );
     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, false);
     61            castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     62            castType->set_lvalue( true ); // xxx - might not need this
     63            dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     64        }
     65        fExpr->get_args().push_back( dstParam );
    6366
    64                 Statement * listInit = srcParam.buildListInit( fExpr );
     67        Statement * listInit = srcParam.buildListInit( fExpr );
    6568
    66                 std::list< Expression * > args = *++srcParam;
    67                 fExpr->get_args().splice( fExpr->get_args().end(), args );
     69        std::list< Expression * > args = *++srcParam;
     70        fExpr->get_args().splice( fExpr->get_args().end(), args );
    6871
    69                 *out++ = new ExprStmt( noLabels, fExpr );
     72        *out++ = new ExprStmt( noLabels, fExpr );
    7073
    71                 srcParam.clearArrayIndices();
     74        srcParam.clearArrayIndices();
    7275
    73                 return listInit;
     76        return listInit;
     77    }
     78
     79    /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     80    /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     81    template< typename OutputIterator >
     82        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     83        static UniqueName indexName( "_index" );
     84
     85        // for a flexible array member nothing is done -- user must define own assignment
     86        if ( ! array->get_dimension() ) return ;
     87
     88        Expression * begin, * end, * update, * cmp;
     89        if ( forward ) {
     90            // generate: for ( int i = 0; i < N; ++i )
     91            begin = new ConstantExpr( Constant::from_int( 0 ) );
     92            end = array->get_dimension()->clone();
     93            cmp = new NameExpr( "?<?" );
     94            update = new NameExpr( "++?" );
     95        } else {
     96            // generate: for ( int i = N-1; i >= 0; --i )
     97            begin = new UntypedExpr( new NameExpr( "?-?" ) );
     98            ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     99            ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
     100            end = new ConstantExpr( Constant::from_int( 0 ) );
     101            cmp = new NameExpr( "?>=?" );
     102            update = new NameExpr( "--?" );
    74103        }
    75104
    76         /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    77         /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    78         template< typename OutputIterator >
    79         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
    80                 static UniqueName indexName( "_index" );
     105        ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
    81106
    82                 // for a flexible array member nothing is done -- user must define own assignment
    83                 if ( ! array->get_dimension() ) return ;
     107        UntypedExpr *cond = new UntypedExpr( cmp );
     108        cond->get_args().push_back( new VariableExpr( index ) );
     109        cond->get_args().push_back( end );
    84110
    85                 Expression * begin, * end, * update, * cmp;
    86                 if ( forward ) {
    87                         // generate: for ( int i = 0; i < N; ++i )
    88                         begin = new ConstantExpr( Constant::from_int( 0 ) );
    89                         end = array->get_dimension()->clone();
    90                         cmp = new NameExpr( "?<?" );
    91                         update = new NameExpr( "++?" );
    92                 } else {
    93                         // generate: for ( int i = N-1; i >= 0; --i )
    94                         begin = new UntypedExpr( new NameExpr( "?-?" ) );
    95                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    96                         ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
    97                         end = new ConstantExpr( Constant::from_int( 0 ) );
    98                         cmp = new NameExpr( "?>=?" );
    99                         update = new NameExpr( "--?" );
    100                 }
     111        UntypedExpr *inc = new UntypedExpr( update );
     112        inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    101113
    102                 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
     114        UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     115        dstIndex->get_args().push_back( dstParam );
     116        dstIndex->get_args().push_back( new VariableExpr( index ) );
     117        dstParam = dstIndex;
    103118
    104                 UntypedExpr *cond = new UntypedExpr( cmp );
    105                 cond->get_args().push_back( new VariableExpr( index ) );
    106                 cond->get_args().push_back( end );
     119        // srcParam must keep track of the array indices to build the
     120        // source parameter and/or array list initializer
     121        srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
    107122
    108                 UntypedExpr *inc = new UntypedExpr( update );
    109                 inc->get_args().push_back( new VariableExpr( index ) );
     123        // for stmt's body, eventually containing call
     124        CompoundStmt * body = new CompoundStmt( noLabels );
     125        Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
    110126
    111                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    112                 dstIndex->get_args().push_back( dstParam );
    113                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    114                 dstParam = dstIndex;
     127        // block containing for stmt and index variable
     128        std::list<Statement *> initList;
     129        CompoundStmt * block = new CompoundStmt( noLabels );
     130        block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     131        if ( listInit ) block->get_kids().push_back( listInit );
     132        block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    115133
    116                 // srcParam must keep track of the array indices to build the
    117                 // source parameter and/or array list initializer
    118                 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
     134        *out++ = block;
     135    }
    119136
    120                 // for stmt's body, eventually containing call
    121                 CompoundStmt * body = new CompoundStmt( noLabels );
    122                 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     137    template< typename OutputIterator >
     138        Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     139        if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     140            genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     141            return 0;
     142        } else {
     143            return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     144        }
     145    }
    123146
    124                 // block containing for stmt and index variable
    125                 std::list<Statement *> initList;
    126                 CompoundStmt * block = new CompoundStmt( noLabels );
    127                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    128                 if ( listInit ) block->get_kids().push_back( listInit );
    129                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     147    /// inserts into out a generated call expression to function fname with arguments dstParam
     148    /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     149    /// object being constructed. The function wraps constructor and destructor calls in an
     150    /// ImplicitCtorDtorStmt node.
     151    template< typename OutputIterator >
     152        void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     153        ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     154        assert( obj );
     155        // unnamed bit fields are not copied as they cannot be accessed
     156        if ( isUnnamedBitfield( obj ) ) return;
    130157
    131                 *out++ = block;
     158        bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
     159        std::list< Statement * > stmts;
     160        genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
     161
     162        // 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
     163        assert( stmts.size() <= 1 );
     164        if ( stmts.size() == 1 ) {
     165            Statement * callStmt = stmts.front();
     166            if ( addCast ) {
     167                // implicitly generated ctor/dtor calls should be wrapped
     168                // so that later passes are aware they were generated.
     169                // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     170                // because this causes the address to be taken at codegen, which is illegal in C.
     171                callStmt = new ImplicitCtorDtorStmt( callStmt );
     172            }
     173            *out++ = callStmt;
    132174        }
    133 
    134         template< typename OutputIterator >
    135         Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    136                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    137                         genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    138                         return 0;
    139                 } else {
    140                         return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    141                 }
    142         }
    143 
    144         /// inserts into out a generated call expression to function fname with arguments dstParam
    145         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    146         /// object being constructed. The function wraps constructor and destructor calls in an
    147         /// ImplicitCtorDtorStmt node.
    148         template< typename OutputIterator >
    149         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    150                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    151                 assert( obj );
    152                 // unnamed bit fields are not copied as they cannot be accessed
    153                 if ( isUnnamedBitfield( obj ) ) return;
    154 
    155                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    156                 std::list< Statement * > stmts;
    157                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    158 
    159                 // 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
    160                 assert( stmts.size() <= 1 );
    161                 if ( stmts.size() == 1 ) {
    162                         Statement * callStmt = stmts.front();
    163                         if ( addCast ) {
    164                                 // implicitly generated ctor/dtor calls should be wrapped
    165                                 // so that later passes are aware they were generated.
    166                                 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    167                                 // because this causes the address to be taken at codegen, which is illegal in C.
    168                                 callStmt = new ImplicitCtorDtorStmt( callStmt );
    169                         }
    170                         *out++ = callStmt;
    171                 }
    172         }
     175    }
    173176} // namespace SymTab
    174177#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.