Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    r6cf27a07 rcad355a  
    2424
    2525namespace SymTab {
    26         /// Generates assignment operators, constructors, and destructor for aggregate types as required
    27         void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     26  /// Generates assignment operators, constructors, and destructor for aggregate types as required
     27  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2828
    29         /// returns true if obj's name is the empty string and it has a bitfield width
    30         bool isUnnamedBitfield( ObjectDecl * obj );
     29  // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
     30  // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
    3131
    32         /// size_t type - set when size_t typedef is seen. Useful in a few places,
    33         /// such as in determining array dimension type
    34         extern Type * SizeType;
     32  /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     33  /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     34  template< typename OutputIterator >
     35  void makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) {
     36    static UniqueName indexName( "_index" );
    3537
    36         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    37         template< typename OutputIterator >
    38         void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward = true );
     38    // for a flexible array member nothing is done -- user must define own assignment
     39    if ( ! array->get_dimension() ) return;
    3940
    40         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    41         template< typename OutputIterator >
    42         void genScalarCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out ) {
    43                 // want to be able to generate assignment, ctor, and dtor generically,
    44                 // so fname is either ?=?, ?{}, or ^?{}
    45                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     41    Expression * begin, * end, * update, * cmp;
     42    if ( forward ) {
     43      // generate: for ( int i = 0; i < 0; ++i )
     44      begin = new NameExpr( "0" );
     45      end = array->get_dimension()->clone();
     46      cmp = new NameExpr( "?<?" );
     47      update = new NameExpr( "++?" );
     48    } else {
     49      // generate: for ( int i = N-1; i >= 0; --i )
     50      begin = new UntypedExpr( new NameExpr( "?-?" ) );
     51      ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     52      ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
     53      end = new NameExpr( "0" );
     54      cmp = new NameExpr( "?>=?" );
     55      update = new NameExpr( "--?" );
     56    }
    4657
    47                 // do something special for unnamed members
    48                 fExpr->get_args().push_back( new AddressExpr( dstParam ) );
     58    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    4959
    50                 if ( srcParam ) {
    51                         fExpr->get_args().push_back( srcParam );
    52                 }
     60    UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     61    init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     62    init->get_args().push_back( begin );
     63    index->set_init( new SingleInit( init, std::list<Expression*>() ) );
    5364
    54                 *out++ = new ExprStmt( noLabels, fExpr );
    55         }
     65    UntypedExpr *cond = new UntypedExpr( cmp );
     66    cond->get_args().push_back( new VariableExpr( index ) );
     67    cond->get_args().push_back( end );
    5668
    57         /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    58         /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    59         template< typename OutputIterator >
    60         void genArrayCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool forward = true ) {
    61                 static UniqueName indexName( "_index" );
     69    UntypedExpr *inc = new UntypedExpr( update );
     70    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    6271
    63                 // for a flexible array member nothing is done -- user must define own assignment
    64                 if ( ! array->get_dimension() ) return ;
     72    // want to be able to generate assignment, ctor, and dtor generically,
     73    // so fname is either ?=?, ?{}, or ^?{}
     74    UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    6575
    66                 Expression * begin, * end, * update, * cmp;
    67                 if ( forward ) {
    68                         // generate: for ( int i = 0; i < 0; ++i )
    69                         begin = new NameExpr( "0" );
    70                         end = array->get_dimension()->clone();
    71                         cmp = new NameExpr( "?<?" );
    72                         update = new NameExpr( "++?" );
    73                 } else {
    74                         // generate: for ( int i = N-1; i >= 0; --i )
    75                         begin = new UntypedExpr( new NameExpr( "?-?" ) );
    76                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    77                         ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
    78                         end = new NameExpr( "0" );
    79                         cmp = new NameExpr( "?>=?" );
    80                         update = new NameExpr( "--?" );
    81                 }
     76    UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
     77    dstIndex->get_args().push_back( dstParam );
     78    dstIndex->get_args().push_back( new VariableExpr( index ) );
     79    fExpr->get_args().push_back( dstIndex );
    8280
    83                 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     81    // srcParam is NULL for default ctor/dtor
     82    if ( srcParam ) {
     83      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     84      srcIndex->get_args().push_back( srcParam );
     85      srcIndex->get_args().push_back( new VariableExpr( index ) );
     86      fExpr->get_args().push_back( srcIndex );
     87    }
    8488
    85                 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    86                 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    87                 init->get_args().push_back( begin );
    88                 index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     89    std::list<Statement *> initList;
     90    CompoundStmt * block = new CompoundStmt( noLabels );
     91    block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     92    block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) );
    8993
    90                 UntypedExpr *cond = new UntypedExpr( cmp );
    91                 cond->get_args().push_back( new VariableExpr( index ) );
    92                 cond->get_args().push_back( end );
    93 
    94                 UntypedExpr *inc = new UntypedExpr( update );
    95                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    96 
    97                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    98                 dstIndex->get_args().push_back( dstParam );
    99                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    100                 dstParam = dstIndex;
    101 
    102                 // srcParam is NULL for default ctor/dtor
    103                 if ( srcParam ) {
    104                         UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    105                         srcIndex->get_args().push_back( srcParam );
    106                         srcIndex->get_args().push_back( new VariableExpr( index ) );
    107                         srcParam = srcIndex;
    108                 }
    109 
    110                 // for stmt's body, eventually containing call
    111                 CompoundStmt * body = new CompoundStmt( noLabels );
    112                 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), forward );
    113 
    114                 // block containing for stmt and index variable
    115                 std::list<Statement *> initList;
    116                 CompoundStmt * block = new CompoundStmt( noLabels );
    117                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    118                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    119 
    120                 *out++ = block;
    121         }
    122 
    123         template< typename OutputIterator >
    124         void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward ) {
    125                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    126                         genArrayCall( srcParam, dstParam, fname, out, at, forward );
    127                 } else {
    128                         genScalarCall( srcParam, dstParam, fname, out );
    129                 }
    130         }
    131 
    132         /// inserts into out a generated call expression to function fname with arguments dstParam
    133         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    134         /// object being constructed. The function wraps constructor and destructor calls in an
    135         /// ImplicitCtorDtorStmt node.
    136         template< typename OutputIterator >
    137         void genImplicitCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    138                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    139                 assert( obj );
    140                 // unnamed bit fields are not copied as they cannot be accessed
    141                 if ( isUnnamedBitfield( obj ) ) return;
    142 
    143                 std::list< Statement * > stmts;
    144                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward );
    145 
    146                 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
    147                 assert( stmts.size() <= 1 );
    148     if ( stmts.size() == 1 ) {
    149                 Statement * callStmt = stmts.front();
    150                 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
    151                         // implicitly generated ctor/dtor calls should be wrapped
    152                         // so that later passes are aware they were generated.
    153                         // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    154                         // because this causes the address to be taken at codegen, which is illegal in C.
    155                         callStmt = new ImplicitCtorDtorStmt( callStmt );
    156                 }
    157                 *out++ = callStmt;
     94    Statement * stmt = block;
     95    if ( fname == "?{}" || fname == "^?{}" ) {
     96      // implicitly generated ctor/dtor calls should be wrapped
     97      // so that later passes are aware they were generated
     98      stmt = new ImplicitCtorDtorStmt( stmt );
    15899    }
    159         }
     100    *out++ = stmt;
     101  }
    160102} // namespace SymTab
    161103#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.