Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    r4d2434a rcad355a  
    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         void 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         template< typename OutputIterator >
    43         void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    44                 // want to be able to generate assignment, ctor, and dtor generically,
    45                 // so fname is either ?=?, ?{}, or ^?{}
    46                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    47 
    48                 // do something special for unnamed members
    49                 dstParam = new AddressExpr( dstParam );
    50                 if ( addCast ) {
    51                         // cast to T* with qualifiers removed, so that qualified objects can be constructed
    52                         // and destructed with the same functions as non-qualified objects.
    53                         // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    54                         // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    55                         // remove lvalue as a qualifier, this can change to
    56                         //   type->get_qualifiers() = Type::Qualifiers();
    57                         assert( type );
    58                         Type * castType = type->clone();
    59                         castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
    60                         castType->set_isLvalue( true ); // xxx - might not need this
    61                         dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    62                 }
    63                 fExpr->get_args().push_back( dstParam );
    64 
    65     Statement * listInit = srcParam.buildListInit( fExpr );
    66     if ( listInit ) {
    67       *out++ = listInit;
     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( "--?" );
    6856    }
    6957
    70     std::list< Expression * > args = *++srcParam;
    71     fExpr->get_args().splice( fExpr->get_args().end(), args );
     58    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    7259
    73                 *out++ = new ExprStmt( noLabels, 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*>() ) );
    7464
    75     srcParam.clearArrayIndices();
    76         }
     65    UntypedExpr *cond = new UntypedExpr( cmp );
     66    cond->get_args().push_back( new VariableExpr( index ) );
     67    cond->get_args().push_back( end );
    7768
    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" );
     69    UntypedExpr *inc = new UntypedExpr( update );
     70    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    8371
    84                 // for a flexible array member nothing is done -- user must define own assignment
    85                 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 ) );
    8675
    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                 }
     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 );
    10380
    104                 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    }
    10588
    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*>() ) );
     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 ) ) );
    11093
    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                 // if ( srcParam ) {
    128                 //      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    129                 //      srcIndex->get_args().push_back( srcParam );
    130                 //      srcIndex->get_args().push_back( new VariableExpr( index ) );
    131                 //      srcParam = srcIndex;
    132                 // }
    133 
    134                 // for stmt's body, eventually containing call
    135                 CompoundStmt * body = new CompoundStmt( noLabels );
    136                 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
    137 
    138                 // block containing for stmt and index variable
    139                 std::list<Statement *> initList;
    140                 CompoundStmt * block = new CompoundStmt( noLabels );
    141                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    142                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    143 
    144                 *out++ = block;
    145         }
    146 
    147         template< typename OutputIterator >
    148         void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    149                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    150                         genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    151                 } else {
    152                         genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    153                 }
    154         }
    155 
    156         /// inserts into out a generated call expression to function fname with arguments dstParam
    157         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    158         /// object being constructed. The function wraps constructor and destructor calls in an
    159         /// ImplicitCtorDtorStmt node.
    160         template< typename OutputIterator >
    161         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    162                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    163                 assert( obj );
    164                 // unnamed bit fields are not copied as they cannot be accessed
    165                 if ( isUnnamedBitfield( obj ) ) return;
    166 
    167                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    168                 std::list< Statement * > stmts;
    169                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    170 
    171                 // 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
    172                 assert( stmts.size() <= 1 );
    173     if ( stmts.size() == 1 ) {
    174                 Statement * callStmt = stmts.front();
    175                 if ( addCast ) {
    176                         // implicitly generated ctor/dtor calls should be wrapped
    177                         // so that later passes are aware they were generated.
    178                         // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    179                         // because this causes the address to be taken at codegen, which is illegal in C.
    180                         callStmt = new ImplicitCtorDtorStmt( callStmt );
    181                 }
    182                 *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 );
    18399    }
    184         }
     100    *out++ = stmt;
     101  }
    185102} // namespace SymTab
    186103#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.