Changeset 108f3cdb for src


Ignore:
Timestamp:
Sep 12, 2017, 10:45:01 AM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
93389c1
Parents:
1395748
Message:

Fix generation of assignment and autogenerate constructors and destructors for opaque type declarations

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/Common/utility.h

    r1395748 r108f3cdb  
    370370}
    371371
     372// -----------------------------------------------------------------------------
     373// Helper struct and function to support
     374// for ( val : lazy_map( container1, f ) ) {}
     375// syntax to have a for each that iterates a container, mapping each element by applying f
     376template< typename T, typename Func >
     377struct lambda_iterate_t {
     378        T & ref;
     379        Func f;
     380
     381        struct iterator {
     382                typedef decltype(begin(ref)) Iter;
     383                Iter it;
     384                Func f;
     385                iterator( Iter it, Func f ) : it(it), f(f) {}
     386                iterator & operator++() {
     387                        ++it; return *this;
     388                }
     389                bool operator!=( const iterator &other ) const { return it != other.it; }
     390                auto operator*() const -> decltype(f(*it)) { return f(*it); }
     391        };
     392
     393        lambda_iterate_t( T & ref, Func f ) : ref(ref), f(f) {}
     394
     395        auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }
     396        auto end() const   -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }
     397};
     398
     399template< typename... Args >
     400lambda_iterate_t<Args...> lazy_map( Args &&... args ) {
     401        return lambda_iterate_t<Args...>(std::forward<Args>( args )...);
     402}
     403
     404
     405
    372406// Local Variables: //
    373407// tab-width: 4 //
  • src/ResolvExpr/CastCost.cc

    r1395748 r108f3cdb  
    4545                                }
    4646                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
    47                                 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    4847                                // all typedefs should be gone by this point
    49                                 assert( type );
     48                                TypeDecl *type = safe_dynamic_cast< TypeDecl* >( namedType );
    5049                                if ( type->get_base() ) {
    5150                                        return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
  • src/ResolvExpr/ConversionCost.cc

    r1395748 r108f3cdb  
    9292
    9393        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    94                 PRINT( std::cerr << "convert to reference cost..." << std::endl; )
     94                PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )
    9595                if ( diff > 0 ) {
    9696                        // TODO: document this
     
    128128                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
    129129                        assert( diff == -1 && destAsRef );
     130                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    130131                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
    131132                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
  • src/SymTab/Autogen.cc

    r1395748 r108f3cdb  
    163163                // Routines at global scope marked "static" to prevent multiple definitions in separate translation units
    164164                // because each unit generates copies of the default routines for each aggregate.
    165 //              DeclarationNode::StorageClass sc = functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static;
    166165                Type::StorageClasses scs = functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static );
    167166                LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
     
    186185        /// using map and t, determines if is constructable, etc.
    187186        bool lookup( const TypeMap & map, Type * t ) {
     187                assertf( t, "Autogenerate lookup was given non-type: %s", toString( t ).c_str() );
    188188                if ( dynamic_cast< PointerType * >( t ) ) {
    189189                        // will need more complicated checking if we want this to work with pointer types, since currently
     
    200200
    201201        /// using map and aggr, examines each member to determine if constructor, etc. should be generated
    202         template<typename AggrDecl>
    203         bool shouldGenerate( const TypeMap & map, AggrDecl * aggr ) {
    204                 for ( Declaration * dcl : aggr->get_members() ) {
    205                         if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( dcl ) ) {
    206                                 if ( ! lookup( map, dwt->get_type() ) ) return false;
    207                         }
     202        template<typename Container>
     203        bool shouldGenerate( const TypeMap & map, const Container & container ) {
     204                for ( Type * t : container ) {
     205                        if ( ! lookup( map, t ) ) return false;
    208206                }
    209207                return true;
     
    211209
    212210        /// data structure for abstracting the generation of special functions
    213         template< typename OutputIterator >
     211        template< typename OutputIterator, typename Container >
    214212        struct FuncGenerator {
    215                 StructDecl *aggregateDecl;
    216                 StructInstType *refType;
     213                const Container & container;
     214                Type *refType;
    217215                unsigned int functionNesting;
    218216                const std::list< TypeDecl* > & typeParams;
    219217                OutputIterator out;
    220                 FuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : aggregateDecl( aggregateDecl ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {}
     218                FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {}
    221219
    222220                /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map.
    223221                void gen( const FuncData & data, bool concurrent_type ) {
    224                         if ( ! shouldGenerate( data.map, aggregateDecl ) ) return;
     222                        if ( ! shouldGenerate( data.map, container ) ) return;
    225223                        FunctionType * ftype = data.genType( refType );
    226224
    227225                        if(concurrent_type && CodeGen::isDestructor( data.fname )) {
    228                                 ftype->get_parameters().front()->get_type()->set_mutex( true );
    229                         }
    230 
    231                         cloneAll( typeParams, ftype->get_forall() );
     226                                ftype->parameters.front()->get_type()->set_mutex( true );
     227                        }
     228
     229                        cloneAll( typeParams, ftype->forall );
    232230                        *out++ = genFunc( data.fname, ftype, functionNesting );
    233231                        data.map.insert( Mangler::mangleType( refType ), true );
     
    235233        };
    236234
    237         template< typename OutputIterator >
    238         FuncGenerator<OutputIterator> makeFuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) {
    239                 return FuncGenerator<OutputIterator>( aggregateDecl, refType, functionNesting, typeParams, out );
     235        template< typename OutputIterator, typename Container >
     236        FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) {
     237                return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, typeParams, out );
    240238        }
    241239
     
    393391        }
    394392
     393        Type * declToType( Declaration * decl ) {
     394                if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
     395                        return dwt->get_type();
     396                }
     397                return nullptr;
     398        }
     399
    395400        /// generates struct constructors, destructor, and assignment functions
    396401        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
     
    406411                // generate each of the functions based on the supplied FuncData objects
    407412                std::list< FunctionDecl * > newFuncs;
    408                 auto generator = makeFuncGenerator( aggregateDecl, refType, functionNesting, typeParams, back_inserter( newFuncs ) );
     413                // structure that iterates aggregate decl members, returning their types
     414                auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, typeParams, back_inserter( newFuncs ) );
    409415                for ( const FuncData & d : data ) {
    410416                        generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() );
     
    605611        }
    606612
     613        Type * declToTypeDeclBase( Declaration * decl ) {
     614                if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {
     615                        return td->base;
     616                }
     617                return nullptr;
     618        }
     619
     620        // generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
    607621        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
    608                 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
    609                 typeInst->set_baseType( typeDecl );
    610                 ObjectDecl *src = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, typeInst->clone(), nullptr );
    611                 ObjectDecl *dst = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), typeInst->clone() ), nullptr );
    612 
    613                 std::list< Statement * > stmts;
    614                 if ( typeDecl->get_base() ) {
    615                         // xxx - generate ctor/dtors for typedecls, e.g.
    616                         // otype T = int *;
    617                         UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
    618                         assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
    619                         assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
    620                         stmts.push_back( new ReturnStmt( std::list< Label >(), assign ) );
    621                 } // if
    622                 FunctionType *type = new FunctionType( Type::Qualifiers(), false );
    623                 type->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, typeInst, 0 ) );
    624                 type->get_parameters().push_back( dst );
    625                 type->get_parameters().push_back( src );
    626                 FunctionDecl *func = genFunc( "?=?", type, functionNesting );
    627                 func->get_statements()->get_kids() = stmts;
    628                 declsToAddAfter.push_back( func );
     622                if ( ! typeDecl->base ) return;
     623
     624                // generate each of the functions based on the supplied FuncData objects
     625                std::list< FunctionDecl * > newFuncs;
     626                std::list< Declaration * > tds { typeDecl };
     627                std::list< TypeDecl * > typeParams;
     628                TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl );
     629                auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, typeParams, back_inserter( newFuncs ) );
     630                for ( const FuncData & d : data ) {
     631                        generator.gen( d, false );
     632                }
     633
     634                if ( functionNesting == 0 ) {
     635                        // forward declare if top-level struct, so that
     636                        // type is complete as soon as its body ends
     637                        // Note: this is necessary if we want structs which contain
     638                        // generic (otype) structs as members.
     639                        for ( FunctionDecl * dcl : newFuncs ) {
     640                                addForwardDecl( dcl, declsToAddAfter );
     641                        }
     642                }
     643
     644                for ( FunctionDecl * dcl : newFuncs ) {
     645                        FunctionType * ftype = dcl->type;
     646                        assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() );
     647                        DeclarationWithType * dst = ftype->parameters.front();
     648                        DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr;
     649                        // generate appropriate calls to member ctor, assignment
     650                        // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
     651                        UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) );
     652                        expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
     653                        if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
     654                        dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) );
     655                        if ( CodeGen::isAssignment( dcl->get_name() ) ) {
     656                                // assignment needs to return a value
     657                                FunctionType * assignType = dcl->type;
     658                                assert( assignType->parameters.size() == 2 );
     659                                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->parameters.back() );
     660                                dcl->statements->kids.push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     661                        }
     662                        declsToAddAfter.push_back( dcl );
     663                }
    629664        }
    630665
Note: See TracChangeset for help on using the changeset viewer.