Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    rb4f8808 rba3706f  
    1717
    1818#include <cassert>                // for assert
    19 #include <iterator>               // for back_inserter
    2019#include <string>                 // for string
    2120
    22 #include "AST/Decl.hpp"
    23 #include "AST/Expr.hpp"
    24 #include "AST/Init.hpp"
    25 #include "AST/Node.hpp"
    26 #include "AST/Stmt.hpp"
    27 #include "AST/Type.hpp"
    2821#include "CodeGen/OperatorTable.h"
    2922#include "Common/UniqueName.h"    // for UniqueName
    30 #include "Common/utility.h"       // for splice
    3123#include "InitTweak/InitTweak.h"  // for InitExpander
    3224#include "SynTree/Constant.h"     // for Constant
     
    4436        /// returns true if obj's name is the empty string and it has a bitfield width
    4537        bool isUnnamedBitfield( ObjectDecl * obj );
    46         bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    47 
    48         /// generate the type of an assignment function for paramType.
    49         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    50         FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
    51 
    52         /// generate the type of a default constructor or destructor for paramType.
    53         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    54         FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    55 
    56         /// generate the type of a copy constructor for paramType.
    57         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    58         FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    59 
    60         /// Enum for loop direction
    61         enum LoopDirection { LoopBackward, LoopForward };
     38
     39        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     40        /// such as in determining array dimension type
     41        extern Type * SizeType;
     42
     43        /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
     44        /// Useful for creating dereference ApplicationExprs without a full resolver pass.
     45        extern FunctionDecl * dereferenceOperator;
     46
     47        // generate the type of an assignment function for paramType
     48        FunctionType * genAssignType( Type * paramType );
     49
     50        // generate the type of a default constructor or destructor for paramType
     51        FunctionType * genDefaultType( Type * paramType );
     52
     53        // generate the type of a copy constructor for paramType
     54        FunctionType * genCopyType( Type * paramType );
    6255
    6356        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    6457        template< typename OutputIterator >
    65         Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    66 
    67         template< typename OutIter >
    68         ast::ptr< ast::Stmt > genCall(
    69                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    70                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    71                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
     58        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    7259
    7360        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    7461        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    7562        template< typename OutputIterator >
    76         Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
     63        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    7764                bool isReferenceCtorDtor = false;
    7865                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    9784                        //   type->get_qualifiers() = Type::Qualifiers();
    9885                        Type * castType = addCast->clone();
    99                         castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     86                        castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    10087                        // castType->set_lvalue( true ); // xxx - might not need this
    10188                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
     
    124111        }
    125112
    126         /// inserts into out a generated call expression to function fname with arguments dstParam and
    127         /// srcParam. Should only be called with non-array types.
    128         /// optionally returns a statement which must be inserted prior to the containing loop, if
    129         /// there is one
    130         template< typename OutIter >
    131         ast::ptr< ast::Stmt > genScalarCall(
    132                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    133                 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
    134                 const ast::Type * addCast = nullptr
    135         ) {
    136                 bool isReferenceCtorDtor = false;
    137                 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
    138                         // reference constructors are essentially application of the rebind operator.
    139                         // apply & to both arguments, do not need a cast
    140                         fname = "?=?";
    141                         dstParam = new ast::AddressExpr{ dstParam };
    142                         addCast = nullptr;
    143                         isReferenceCtorDtor = true;
    144                 }
    145 
    146                 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
    147                 // "?=?", "?{}", or "^?{}"
    148                 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
    149 
    150                 if ( addCast ) {
    151                         // cast to T& with qualifiers removed, so that qualified objects can be constructed and
    152                         // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
    153                         // is considered a qualifier - for AddressExpr to resolve, its argument must have an
    154                         // lvalue-qualified type, so remove all qualifiers except lvalue.
    155                         // xxx -- old code actually removed lvalue too...
    156                         ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
    157                         ast::ptr< ast::Type > castType = addCast;
    158                         ast::remove_qualifiers(
    159                                 castType,
    160                                 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
    161                         dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
    162                 }
    163                 fExpr->args.emplace_back( dstParam );
    164 
    165                 const ast::Stmt * listInit = srcParam.buildListInit( fExpr );
    166 
    167                 // fetch next set of arguments
    168                 ++srcParam;
    169 
    170                 // return if adding reference fails -- will happen on default ctor and dtor
    171                 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
    172 
    173                 std::vector< ast::ptr< ast::Expr > > args = *srcParam;
    174                 splice( fExpr->args, args );
    175 
    176                 *out++ = new ast::ExprStmt{ loc, fExpr };
    177 
    178                 srcParam.clearArrayIndices();
    179                
    180                 return listInit;
    181         }
    182 
    183113        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    184114        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    185115        template< typename OutputIterator >
    186         void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
     116        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    187117                static UniqueName indexName( "_index" );
    188118
     
    245175        }
    246176
    247         /// Store in out a loop which calls fname on each element of the array with srcParam and
    248         /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
    249         template< typename OutIter >
    250         void genArrayCall(
    251                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    252                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    253                 const ast::ArrayType * array, const ast::Type * addCast = nullptr,
    254                 LoopDirection forward = LoopForward
    255         ) {
    256                 static UniqueName indexName( "_index" );
    257 
    258                 // for a flexible array member nothing is done -- user must define own assignment
    259                 if ( ! array->dimension ) return;
    260 
    261                 if ( addCast ) {
    262                         // peel off array layer from cast
    263                         addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
    264                 }
    265 
    266                 ast::ptr< ast::Expr > begin, end, cmp, update;
    267 
    268                 if ( forward ) {
    269                         // generate: for ( int i = 0; i < N; ++i )
    270                         begin = ast::ConstantExpr::from_int( loc, 0 );
    271                         end = array->dimension;
    272                         cmp = new ast::NameExpr{ loc, "?<?" };
    273                         update = new ast::NameExpr{ loc, "++?" };
    274                 } else {
    275                         // generate: for ( int i = N-1; i >= 0; --i )
    276                         begin = new ast::UntypedExpr{
    277                                 loc, new ast::NameExpr{ loc, "?-?" },
    278                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
    279                         end = ast::ConstantExpr::from_int( loc, 0 );
    280                         cmp = new ast::NameExpr{ loc, "?>=?" };
    281                         update = new ast::NameExpr{ loc, "--?" };
    282                 }
    283 
    284                 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
    285                         loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    286                         new ast::SingleInit{ loc, begin } };
    287                
    288                 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
    289                         loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
    290                
    291                 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
    292                         loc, update, { new ast::VariableExpr{ loc, index } } };
    293                
    294                 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
    295                         loc, new ast::NameExpr{ loc, "?[?]" },
    296                         { dstParam, new ast::VariableExpr{ loc, index } } };
    297                
    298                 // srcParam must keep track of the array indices to build the source parameter and/or
    299                 // array list initializer
    300                 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
    301 
    302                 // for stmt's body, eventually containing call
    303                 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
    304                 ast::ptr< ast::Stmt > listInit = genCall(
    305                         srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
    306                         forward );
    307                
    308                 // block containing the stmt and index variable
    309                 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
    310                 block->push_back( new ast::DeclStmt{ loc, index } );
    311                 if ( listInit ) { block->push_back( listInit ); }
    312                 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
    313 
    314                 *out++ = block;
    315         }
    316 
    317         template< typename OutputIterator >
    318         Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     177        template< typename OutputIterator >
     178        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    319179                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    320180                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    325185        }
    326186
    327         template< typename OutIter >
    328         ast::ptr< ast::Stmt > genCall(
    329                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    330                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    331                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward
    332         ) {
    333                 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
    334                         genArrayCall(
    335                                 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
    336                                 forward );
    337                         return {};
    338                 } else {
    339                         return genScalarCall(
    340                                 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    341                 }
    342         }
    343 
    344187        /// inserts into out a generated call expression to function fname with arguments dstParam
    345188        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     
    347190        /// ImplicitCtorDtorStmt node.
    348191        template< typename OutputIterator >
    349         void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     192        void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    350193                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    351194                assert( obj );
     
    375218                }
    376219        }
    377 
    378         static inline ast::ptr< ast::Stmt > genImplicitCall(
    379                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    380                 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
    381                 LoopDirection forward = LoopForward
    382         ) {
    383                 // unnamed bit fields are not copied as they cannot be accessed
    384                 if ( isUnnamedBitfield( obj ) ) return {};
    385 
    386                 ast::ptr< ast::Type > addCast = nullptr;
    387                 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    388                         assert( dstParam->result );
    389                         addCast = dstParam->result;
    390                 }
    391 
    392                 std::vector< ast::ptr< ast::Stmt > > stmts;
    393                 genCall(
    394                         srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
    395 
    396                 if ( stmts.empty() ) {
    397                         return {};
    398                 } else if ( stmts.size() == 1 ) {
    399                         const ast::Stmt * callStmt = stmts.front();
    400                         if ( addCast ) {
    401                                 // implicitly generated ctor/dtor calls should be wrapped so that later passes are
    402                                 // aware they were generated.
    403                                 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
    404                         }
    405                         return callStmt;
    406                 } else {
    407                         assert( false );
    408                         return {};
    409                 }
    410         }
    411220} // namespace SymTab
    412221
Note: See TracChangeset for help on using the changeset viewer.