Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    r6b0b624 rd56e5bc  
    1010// Created On       : Sun May 17 21:53:34 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:50:25 2017
    13 // Update Count     : 15
     12// Last Modified On : Wed Jun 21 17:25:26 2017
     13// Update Count     : 14
    1414//
    1515
    16 #pragma once
     16#ifndef AUTOGEN_H
     17#define AUTOGEN_H
    1718
    1819#include <string>
     
    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         /// returns true if obj's name is the empty string and it has a bitfield width
    30         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 );
    3132
    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;
     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;
    3536
    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 >
     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 >
    3839        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    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         /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    42         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 >
    4344        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    4445        // want to be able to generate assignment, ctor, and dtor generically,
     
    4950        dstParam = new AddressExpr( dstParam );
    5051        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( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    60                 castType->set_lvalue( true ); // xxx - might not need this
    61                 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     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 ) );
    6264        }
    6365        fExpr->get_args().push_back( dstParam );
     
    7375
    7476        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( "--?" );
    75103        }
    76104
    77         /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    78         /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    79         template< typename OutputIterator >
    80         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
    81                 static UniqueName indexName( "_index" );
     105        ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
    82106
    83                 // for a flexible array member nothing is done -- user must define own assignment
    84                 if ( ! array->get_dimension() ) return ;
     107        UntypedExpr *cond = new UntypedExpr( cmp );
     108        cond->get_args().push_back( new VariableExpr( index ) );
     109        cond->get_args().push_back( end );
    85110
    86                 Expression * begin, * end, * update, * cmp;
    87                 if ( forward ) {
    88                         // generate: for ( int i = 0; i < N; ++i )
    89                         begin = new ConstantExpr( Constant::from_int( 0 ) );
    90                         end = array->get_dimension()->clone();
    91                         cmp = new NameExpr( "?<?" );
    92                         update = new NameExpr( "++?" );
    93                 } else {
    94                         // generate: for ( int i = N-1; i >= 0; --i )
    95                         begin = new UntypedExpr( new NameExpr( "?-?" ) );
    96                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    97                         ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
    98                         end = new ConstantExpr( Constant::from_int( 0 ) );
    99                         cmp = new NameExpr( "?>=?" );
    100                         update = new NameExpr( "--?" );
    101                 }
     111        UntypedExpr *inc = new UntypedExpr( update );
     112        inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    102113
    103                 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
     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;
    104118
    105                 UntypedExpr *cond = new UntypedExpr( cmp );
    106                 cond->get_args().push_back( new VariableExpr( index ) );
    107                 cond->get_args().push_back( end );
     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() );
    108122
    109                 UntypedExpr *inc = new UntypedExpr( update );
    110                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     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 );
    111126
    112                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    113                 dstIndex->get_args().push_back( dstParam );
    114                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    115                 dstParam = dstIndex;
     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 ) );
    116133
    117                 // srcParam must keep track of the array indices to build the
    118                 // source parameter and/or array list initializer
    119                 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
     134        *out++ = block;
     135    }
    120136
    121                 // for stmt's body, eventually containing call
    122                 CompoundStmt * body = new CompoundStmt( noLabels );
    123                 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     137    template< typename OutputIterator >
     138        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 );
     144        }
     145    }
    124146
    125                 // block containing for stmt and index variable
    126                 std::list<Statement *> initList;
    127                 CompoundStmt * block = new CompoundStmt( noLabels );
    128                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    129                 if ( listInit ) block->get_kids().push_back( listInit );
    130                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     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 >
     152        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;
    131157
    132                 *out++ = block;
     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 );
     161
     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;
    133174        }
    134 
    135         template< typename OutputIterator >
    136         Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    137                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    138                         genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    139                         return 0;
    140                 } else {
    141                         return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    142                 }
    143         }
    144 
    145         /// inserts into out a generated call expression to function fname with arguments dstParam
    146         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    147         /// object being constructed. The function wraps constructor and destructor calls in an
    148         /// ImplicitCtorDtorStmt node.
    149         template< typename OutputIterator >
    150         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    151                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    152                 assert( obj );
    153                 // unnamed bit fields are not copied as they cannot be accessed
    154                 if ( isUnnamedBitfield( obj ) ) return;
    155 
    156                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    157                 std::list< Statement * > stmts;
    158                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    159 
    160                 // 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
    161                 assert( stmts.size() <= 1 );
    162                 if ( stmts.size() == 1 ) {
    163                         Statement * callStmt = stmts.front();
    164                         if ( addCast ) {
    165                                 // implicitly generated ctor/dtor calls should be wrapped
    166                                 // so that later passes are aware they were generated.
    167                                 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    168                                 // because this causes the address to be taken at codegen, which is illegal in C.
    169                                 callStmt = new ImplicitCtorDtorStmt( callStmt );
    170                         }
    171                         *out++ = callStmt;
    172                 }
    173         }
     175    }
    174176} // namespace SymTab
    175 
    176 // Local Variables: //
    177 // tab-width: 4 //
    178 // mode: c++ //
    179 // compile-command: "make install" //
    180 // End: //
    181 
     177#endif // AUTOGEN_H
Note: See TracChangeset for help on using the changeset viewer.