Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    rcad355a r4d2434a  
    2222#include "SynTree/Declaration.h"
    2323#include "SynTree/Initializer.h"
     24#include "InitTweak/InitTweak.h"
    2425
    2526namespace SymTab {
    26   /// Generates assignment operators, constructors, and destructor for aggregate types as required
    27   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 );
    2829
    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
     30        /// returns true if obj's name is the empty string and it has a bitfield width
     31        bool isUnnamedBitfield( ObjectDecl * obj );
    3132
    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" );
     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;
    3736
    38     // for a flexible array member nothing is done -- user must define own assignment
    39     if ( ! array->get_dimension() ) return;
     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 );
    4040
    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( "--?" );
     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;
    5668    }
    5769
    58     ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     70    std::list< Expression * > args = *++srcParam;
     71    fExpr->get_args().splice( fExpr->get_args().end(), args );
    5972
    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*>() ) );
     73                *out++ = new ExprStmt( noLabels, fExpr );
    6474
    65     UntypedExpr *cond = new UntypedExpr( cmp );
    66     cond->get_args().push_back( new VariableExpr( index ) );
    67     cond->get_args().push_back( end );
     75    srcParam.clearArrayIndices();
     76        }
    6877
    69     UntypedExpr *inc = new UntypedExpr( update );
    70     inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     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" );
    7183
    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 ) );
     84                // for a flexible array member nothing is done -- user must define own assignment
     85                if ( ! array->get_dimension() ) return ;
    7586
    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 );
     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                }
    80103
    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 );
     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                // 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;
    87183    }
    88 
    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 ) ) );
    93 
    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   }
     184        }
    102185} // namespace SymTab
    103186#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.