Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    rd56e5bc r49148d5  
    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         // 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 );
     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 );
    6663
    67         Statement * listInit = srcParam.buildListInit( fExpr );
     64                Statement * listInit = srcParam.buildListInit( fExpr );
    6865
    69         std::list< Expression * > args = *++srcParam;
    70         fExpr->get_args().splice( fExpr->get_args().end(), args );
     66                std::list< Expression * > args = *++srcParam;
     67                fExpr->get_args().splice( fExpr->get_args().end(), args );
    7168
    72         *out++ = new ExprStmt( noLabels, fExpr );
     69                *out++ = new ExprStmt( noLabels, fExpr );
    7370
    74         srcParam.clearArrayIndices();
     71                srcParam.clearArrayIndices();
    7572
    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( "--?" );
     73                return listInit;
    10374        }
    10475
    105         ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
     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" );
    10681
    107         UntypedExpr *cond = new UntypedExpr( cmp );
    108         cond->get_args().push_back( new VariableExpr( index ) );
    109         cond->get_args().push_back( end );
     82                // for a flexible array member nothing is done -- user must define own assignment
     83                if ( ! array->get_dimension() ) return ;
    11084
    111         UntypedExpr *inc = new UntypedExpr( update );
    112         inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     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                }
    113101
    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;
     102                ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
    118103
    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() );
     104                UntypedExpr *cond = new UntypedExpr( cmp );
     105                cond->get_args().push_back( new VariableExpr( index ) );
     106                cond->get_args().push_back( end );
    122107
    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 );
     108                UntypedExpr *inc = new UntypedExpr( update );
     109                inc->get_args().push_back( new VariableExpr( index ) );
    126110
    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 ) );
     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;
    133115
    134         *out++ = block;
    135     }
     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() );
    136119
    137     template< typename OutputIterator >
     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 );
     123
     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 ) );
     130
     131                *out++ = block;
     132        }
     133
     134        template< typename OutputIterator >
    138135        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 );
     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                }
    144142        }
    145     }
    146143
    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 >
     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 >
    152149        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;
     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;
    157154
    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 );
     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 );
    161158
    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;
     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                }
    174172        }
    175     }
    176173} // namespace SymTab
    177174#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.