Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    rd56e5bc r30f9072  
    1717#define AUTOGEN_H
    1818
    19 #include <string>
    20 #include "SynTree/Statement.h"
    21 #include "SynTree/Expression.h"
    22 #include "SynTree/Declaration.h"
    23 #include "SynTree/Initializer.h"
    24 #include "InitTweak/InitTweak.h"
     19#include <cassert>                // for assert
     20#include <iterator>               // for back_insert_iterator, back_inserter
     21#include <list>                   // for list
     22#include <string>                 // for string, operator==
     23
     24#include "Common/UniqueName.h"    // for UniqueName
     25#include "InitTweak/InitTweak.h"  // for InitExpander
     26#include "Parser/LinkageSpec.h"   // for C
     27#include "SynTree/Constant.h"     // for Constant
     28#include "SynTree/Declaration.h"  // for ObjectDecl, Declaration (ptr only)
     29#include "SynTree/Expression.h"   // for UntypedExpr, NameExpr, VariableExpr
     30#include "SynTree/Initializer.h"  // for SingleInit
     31#include "SynTree/Label.h"        // for Label, noLabels
     32#include "SynTree/Statement.h"    // for Statement (ptr only), CompoundStmt
     33#include "SynTree/Type.h"         // for Type, ArrayType, Type::Qualifiers
    2534
    2635namespace SymTab {
    27     /// Generates assignment operators, constructors, and destructor for aggregate types as required
    28     void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     36        /// Generates assignment operators, constructors, and destructor for aggregate types as required
     37        void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2938
    30     /// returns true if obj's name is the empty string and it has a bitfield width
    31     bool isUnnamedBitfield( ObjectDecl * obj );
     39        /// returns true if obj's name is the empty string and it has a bitfield width
     40        bool isUnnamedBitfield( ObjectDecl * obj );
    3241
    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;
     42        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     43        /// such as in determining array dimension type
     44        extern Type * SizeType;
    3645
    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 >
     46        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     47        template< typename OutputIterator >
    3948        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    4049
    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 >
     50        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     51        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
     52        template< typename OutputIterator >
    4453        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    4554        // want to be able to generate assignment, ctor, and dtor generically,
     
    5059        dstParam = new AddressExpr( dstParam );
    5160        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 ) );
     61                // cast to T* with qualifiers removed, so that qualified objects can be constructed
     62                // and destructed with the same functions as non-qualified objects.
     63                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     64                // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     65                // remove lvalue as a qualifier, this can change to
     66                //   type->get_qualifiers() = Type::Qualifiers();
     67                assert( type );
     68                Type * castType = type->clone();
     69                castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     70                castType->set_lvalue( true ); // xxx - might not need this
     71                dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    6472        }
    6573        fExpr->get_args().push_back( dstParam );
     
    7583
    7684        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( "--?" );
    10385        }
    10486
    105         ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
     87        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     88        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     89        template< typename OutputIterator >
     90        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     91                static UniqueName indexName( "_index" );
    10692
    107         UntypedExpr *cond = new UntypedExpr( cmp );
    108         cond->get_args().push_back( new VariableExpr( index ) );
    109         cond->get_args().push_back( end );
     93                // for a flexible array member nothing is done -- user must define own assignment
     94                if ( ! array->get_dimension() ) return ;
    11095
    111         UntypedExpr *inc = new UntypedExpr( update );
    112         inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     96                Expression * begin, * end, * update, * cmp;
     97                if ( forward ) {
     98                        // generate: for ( int i = 0; i < N; ++i )
     99                        begin = new ConstantExpr( Constant::from_int( 0 ) );
     100                        end = array->get_dimension()->clone();
     101                        cmp = new NameExpr( "?<?" );
     102                        update = new NameExpr( "++?" );
     103                } else {
     104                        // generate: for ( int i = N-1; i >= 0; --i )
     105                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
     106                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     107                        ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
     108                        end = new ConstantExpr( Constant::from_int( 0 ) );
     109                        cmp = new NameExpr( "?>=?" );
     110                        update = new NameExpr( "--?" );
     111                }
    113112
    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;
     113                ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
    118114
    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() );
     115                UntypedExpr *cond = new UntypedExpr( cmp );
     116                cond->get_args().push_back( new VariableExpr( index ) );
     117                cond->get_args().push_back( end );
    122118
    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 );
     119                UntypedExpr *inc = new UntypedExpr( update );
     120                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    126121
    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 ) );
     122                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     123                dstIndex->get_args().push_back( dstParam );
     124                dstIndex->get_args().push_back( new VariableExpr( index ) );
     125                dstParam = dstIndex;
    133126
    134         *out++ = block;
    135     }
     127                // srcParam must keep track of the array indices to build the
     128                // source parameter and/or array list initializer
     129                srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
    136130
    137     template< typename OutputIterator >
     131                // for stmt's body, eventually containing call
     132                CompoundStmt * body = new CompoundStmt( noLabels );
     133                Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     134
     135                // block containing for stmt and index variable
     136                std::list<Statement *> initList;
     137                CompoundStmt * block = new CompoundStmt( noLabels );
     138                block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     139                if ( listInit ) block->get_kids().push_back( listInit );
     140                block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     141
     142                *out++ = block;
     143        }
     144
     145        template< typename OutputIterator >
    138146        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 );
     147                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     148                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     149                        return 0;
     150                } else {
     151                        return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     152                }
    144153        }
    145     }
    146154
    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 >
     155        /// inserts into out a generated call expression to function fname with arguments dstParam
     156        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     157        /// object being constructed. The function wraps constructor and destructor calls in an
     158        /// ImplicitCtorDtorStmt node.
     159        template< typename OutputIterator >
    152160        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;
     161                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     162                assert( obj );
     163                // unnamed bit fields are not copied as they cannot be accessed
     164                if ( isUnnamedBitfield( obj ) ) return;
    157165
    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 );
     166                bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) );
     167                std::list< Statement * > stmts;
     168                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    161169
    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;
     170                // 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
     171                assert( stmts.size() <= 1 );
     172                if ( stmts.size() == 1 ) {
     173                        Statement * callStmt = stmts.front();
     174                        if ( addCast ) {
     175                                // implicitly generated ctor/dtor calls should be wrapped
     176                                // so that later passes are aware they were generated.
     177                                // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     178                                // because this causes the address to be taken at codegen, which is illegal in C.
     179                                callStmt = new ImplicitCtorDtorStmt( callStmt );
     180                        }
     181                        *out++ = callStmt;
     182                }
    174183        }
    175     }
    176184} // namespace SymTab
    177185#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.