Changeset 70a06f6 for src/GenPoly


Ignore:
Timestamp:
Apr 14, 2016, 4:13:10 PM (9 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
356189a
Parents:
db4ecc5 (diff), 37f0da8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into ctor

Conflicts:

src/CodeGen/CodeGenerator.cc
src/GenPoly/Box.cc
src/Parser/DeclarationNode.cc
src/Parser/ParseNode.h
src/Parser/parser.cc
src/Parser/parser.yy
src/SymTab/AddVisit.h
src/SymTab/Validate.cc
src/SynTree/Expression.cc
src/SynTree/Expression.h
src/SynTree/Mutator.cc
src/SynTree/Mutator.h
src/SynTree/SynTree.h
src/SynTree/Visitor.cc
src/SynTree/Visitor.h
src/libcfa/iostream.c

Location:
src/GenPoly
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rdb4ecc5 r70a06f6  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Feb 09 14:39:52 2016
     12// Last Modified On : Thu Apr 14 15:57:46 2016
    1313// Update Count     : 295
    1414//
     
    3030#include "FindFunction.h"
    3131#include "ScopedMap.h"
     32#include "ScopedSet.h"
    3233#include "ScrubTyVars.h"
    3334
     
    6263                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
    6364
    64                 /// Key for a unique concrete type; generic base type paired with type parameter list
    65                 struct ConcreteType {
    66                         ConcreteType() : base(NULL), params() {}
    67 
    68                         ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
    69 
    70                         ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
     65                /// Abstracts type equality for a list of parameter types
     66                struct TypeList {
     67                        TypeList() : params() {}
     68                        TypeList( const std::list< Type* > &_params ) : params() { cloneAll(_params, params); }
     69                        TypeList( std::list< Type* > &&_params ) : params( _params ) {}
     70
     71                        TypeList( const TypeList &that ) : params() { cloneAll(that.params, params); }
     72                        TypeList( TypeList &&that ) : params( std::move( that.params ) ) {}
    7173
    7274                        /// Extracts types from a list of TypeExpr*
    73                         ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
     75                        TypeList( const std::list< TypeExpr* >& _params ) : params() {
    7476                                for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
    7577                                        params.push_back( (*param)->get_type()->clone() );
     
    7779                        }
    7880
    79                         ConcreteType& operator= (const ConcreteType& that) {
     81                        TypeList& operator= ( const TypeList &that ) {
    8082                                deleteAll( params );
     83
    8184                                params.clear();
    82 
    83                                 base = that.base;
    8485                                cloneAll( that.params, params );
    8586
     
    8788                        }
    8889
    89                         ~ConcreteType() { deleteAll( params ); }
    90 
    91                         bool operator== (const ConcreteType& that) const {
    92                                 if ( base != that.base ) return false;
     90                        TypeList& operator= ( TypeList &&that ) {
     91                                deleteAll( params );
     92
     93                                params = std::move( that.params );
     94
     95                                return *this;
     96                        }
     97
     98                        ~TypeList() { deleteAll( params ); }
     99
     100                        bool operator== ( const TypeList& that ) const {
     101                                if ( params.size() != that.params.size() ) return false;
    93102
    94103                                SymTab::Indexer dummy;
    95                                 if ( params.size() != that.params.size() ) return false;
    96104                                for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
    97105                                        if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
     
    100108                        }
    101109
    102                         AggregateDecl *base;        ///< Base generic type
    103110                        std::list< Type* > params;  ///< Instantiation parameters
    104111                };
    105112
    106                 /// Maps a concrete type to the some value, accounting for scope
    107                 template< typename Value >
     113                /// Maps a key and a TypeList to the some value, accounting for scope
     114                template< typename Key, typename Value >
    108115                class InstantiationMap {
    109                         /// Information about a specific instantiation of a generic type
    110                         struct Instantiation {
    111                                 ConcreteType key;  ///< Instantiation parameters for this type
    112                                 Value *value;      ///< Value for this instantiation
    113 
    114                                 Instantiation() : key(), value(0) {}
    115                                 Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {}
    116                         };
    117                         /// Map of generic types to instantiations of them
    118                         typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
    119 
    120                         std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
     116                        /// Wraps value for a specific (Key, TypeList) combination
     117                        typedef std::pair< TypeList, Value* > Instantiation;
     118                        /// List of TypeLists paired with their appropriate values
     119                        typedef std::vector< Instantiation > ValueList;
     120                        /// Underlying map type; maps keys to a linear list of corresponding TypeLists and values
     121                        typedef ScopedMap< Key*, ValueList > InnerMap;
     122
     123                        InnerMap instantiations;  ///< instantiations
    121124
    122125                public:
    123126                        /// Starts a new scope
    124                         void beginScope() {
    125                                 Scope scope;
    126                                 scopes.push_back(scope);
    127                         }
     127                        void beginScope() { instantiations.beginScope(); }
    128128
    129129                        /// Ends a scope
    130                         void endScope() {
    131                                 scopes.pop_back();
    132                         }
    133 
    134                         /// Default constructor initializes with one scope
    135                         InstantiationMap() { beginScope(); }
    136 
    137 //              private:
    138                         /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
    139                         /// Returns NULL on none such.
    140                         Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
    141                                 ConcreteType key(generic, params);
    142                                 // scan scopes from innermost out
    143                                 for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
    144                                         // skip scope if no instantiations of this generic type
    145                                         typename Scope::const_iterator insts = scope->find( generic );
    146                                         if ( insts == scope->end() ) continue;
    147                                         // look through instantiations for matches to concrete type
    148                                         for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
    149                                                 if ( inst->key == key ) return inst->value;
     130                        void endScope() { instantiations.endScope(); }
     131
     132                        /// Gets the value for the (key, typeList) pair, returns NULL on none such.
     133                        Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const {
     134                                TypeList typeList( params );
     135
     136                                // scan scopes for matches to the key
     137                                for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) {
     138                                        for ( typename ValueList::const_reverse_iterator inst = insts->second.rbegin(); inst != insts->second.rend(); ++inst ) {
     139                                                if ( inst->first == typeList ) return inst->second;
    150140                                        }
    151141                                }
    152                                 // no matching instantiation found
     142                                // no matching instantiations found
    153143                                return 0;
    154144                        }
    155                 public:
    156 //                      StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
    157 //                      UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
    158 
    159 //              private:
    160                         /// Adds a value for a concrete type to the current scope
    161                         void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, Value *value ) {
    162                                 ConcreteType key(generic, params);
    163                                 scopes.back()[generic].push_back( Instantiation( key, value ) );
    164                         }
    165 //              public:
    166 //                      void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
    167 //                      void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
     145
     146                        /// Adds a value for a (key, typeList) pair to the current scope
     147                        void insert( Key *key, const std::list< TypeExpr* > &params, Value *value ) {
     148                                instantiations[ key ].push_back( Instantiation( TypeList( params ), value ) );
     149                        }
    168150                };
    169151
     
    178160                        virtual Declaration *mutate( UnionDecl *unionDecl );
    179161                };
    180                
     162
    181163                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
    182164                class Pass1 : public PolyMutator {
     
    197179                        virtual void doEndScope();
    198180                  private:
    199                         /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
    200                         Expression *makeOffsetArray( StructInstType *type );
    201181                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
    202182                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
     
    225205                        ObjectDecl *makeTemporary( Type *type );
    226206
    227                         std::map< std::string, DeclarationWithType *> assignOps;
    228                         ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
    229                         ScopedMap< std::string, DeclarationWithType* > adapters;
     207                        ScopedMap< std::string, DeclarationWithType *> assignOps;    ///< Currently known type variable assignment operators
     208                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
     209                        ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
     210
    230211                        DeclarationWithType *retval;
    231212                        bool useRetval;
     
    233214                };
    234215
    235                 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well
     216                /// * Moves polymorphic returns in function types to pointer-type parameters
     217                /// * adds type size and assertion parameters to parameter lists
    236218                class Pass2 : public PolyMutator {
    237219                  public:
     
    244226                        virtual Type *mutate( PointerType *pointerType );
    245227                        virtual Type *mutate( FunctionType *funcType );
     228
    246229                  private:
    247230                        void addAdapters( FunctionType *functionType );
     
    253236                class GenericInstantiator : public DeclMutator {
    254237                        /// Map of (generic type, parameter list) pairs to concrete type instantiations
    255                         InstantiationMap< AggregateDecl > instantiations;
     238                        InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
    256239                        /// Namer for concrete types
    257240                        UniqueName typeNamer;
     
    278261                };
    279262
    280                 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
    281                 /// also fixes offsetof expressions.
    282                 class MemberExprFixer : public PolyMutator {
    283                   public:
     263                /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
     264                /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
     265                /// * Calculates polymorphic offsetof expressions from offset array
     266                /// * Inserts dynamic calculation of polymorphic type layouts where needed
     267                class PolyGenericCalculator : public PolyMutator {
     268                public:
    284269                        template< typename DeclClass >
    285270                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    292277                        virtual Type *mutate( FunctionType *funcType );
    293278                        virtual Expression *mutate( MemberExpr *memberExpr );
     279                        virtual Expression *mutate( SizeofExpr *sizeofExpr );
     280                        virtual Expression *mutate( AlignofExpr *alignofExpr );
    294281                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
     282                        virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
     283
     284                        virtual void doBeginScope();
     285                        virtual void doEndScope();
     286
     287                private:
     288                        /// Makes a new variable in the current scope with the given name, type & optional initializer
     289                        ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
     290                        /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
     291                        bool findGeneric( Type *ty );
     292                        /// adds type parameters to the layout call; will generate the appropriate parameters if needed
     293                        void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
     294
     295                        /// Enters a new scope for type-variables, adding the type variables from ty
     296                        void beginTypeScope( Type *ty );
     297                        /// Exits the type-variable scope
     298                        void endTypeScope();
     299
     300                        ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
     301                        ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
    295302                };
    296303
     
    342349                Pass2 pass2;
    343350                GenericInstantiator instantiator;
    344                 MemberExprFixer memberFixer;
     351                PolyGenericCalculator polyCalculator;
    345352                Pass3 pass3;
    346                
     353
    347354                layoutBuilder.mutateDeclarationList( translationUnit );
    348355                mutateTranslationUnit/*All*/( translationUnit, pass1 );
    349356                mutateTranslationUnit/*All*/( translationUnit, pass2 );
    350 //              instantiateGeneric( translationUnit );
    351357                instantiator.mutateDeclarationList( translationUnit );
    352                 mutateTranslationUnit/*All*/( translationUnit, memberFixer );
     358                mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
    353359                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    354360        }
     
    364370                return functionDecl;
    365371        }
    366        
     372
    367373        /// Get a list of type declarations that will affect a layout function
    368374        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
     
    374380                        }
    375381                }
    376                
     382
    377383                return otypeDecls;
    378384        }
     
    381387        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
    382388                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    383                
     389
    384390                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
    385391                        TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
    386                         layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
    387                         layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     392                        std::string paramName = mangleType( &paramType );
     393                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     394                        layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
    388395                }
    389396        }
    390397
    391398        /// Builds a layout function declaration
    392         FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {
     399        FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {
    393400                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    394401                // because each unit generates copies of the default routines for each aggregate.
    395402                FunctionDecl *layoutDecl = new FunctionDecl(
    396                         "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
     403                        layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
    397404                layoutDecl->fixUniqueId();
    398405                return layoutDecl;
     
    437444                return makeCond( ifCond, ifExpr );
    438445        }
    439        
     446
    440447        /// adds an expression to a compound statement
    441448        void addExpr( CompoundStmt *stmts, Expression *expr ) {
     
    447454                stmts->get_kids().push_back( stmt );
    448455        }
    449        
     456
    450457        Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
    451458                // do not generate layout function for "empty" tag structs
     
    460467                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    461468                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
    462                
    463                 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     469
     470                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
    464471                layoutFnType->get_parameters().push_back( sizeParam );
    465                 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     472                ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
    466473                layoutFnType->get_parameters().push_back( alignParam );
    467                 ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     474                ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
    468475                layoutFnType->get_parameters().push_back( offsetParam );
    469476                addOtypeParams( layoutFnType, otypeParams );
    470477
    471478                // build function decl
    472                 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );
     479                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );
    473480
    474481                // calculate struct layout in function body
     
    490497                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
    491498                        }
    492                        
     499
    493500                        // place current size in the current offset index
    494501                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
     
    498505                        // add member size to current size
    499506                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
    500                        
     507
    501508                        // take max of member alignment and global alignment
    502509                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     
    508515                return structDecl;
    509516        }
    510        
     517
    511518        Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
    512519                // do not generate layout function for "empty" tag unions
    513520                if ( unionDecl->get_members().empty() ) return unionDecl;
    514                
     521
    515522                // get parameters that can change layout, exiting early if none
    516523                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
     
    521528                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    522529                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
    523                
    524                 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     530
     531                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
    525532                layoutFnType->get_parameters().push_back( sizeParam );
    526                 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     533                ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
    527534                layoutFnType->get_parameters().push_back( alignParam );
    528535                addOtypeParams( layoutFnType, otypeParams );
    529536
    530537                // build function decl
    531                 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );
     538                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );
    532539
    533540                // calculate union layout in function body
     
    538545                        assert( dwt );
    539546                        Type *memberType = dwt->get_type();
    540                        
     547
    541548                        // take max member size and global size
    542549                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
    543                        
     550
    544551                        // take max of member alignment and global alignment
    545552                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     
    551558                return unionDecl;
    552559        }
    553        
     560
    554561        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    555562
     
    612619                        return 0;
    613620                }
    614                
     621
    615622                /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
    616623                /// Only picks assignments where neither parameter is cv-qualified
     
    624631                                                Type *paramType2 = funType->get_parameters().back()->get_type();
    625632                                                if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
    626                                                
     633
    627634                                                if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
    628635                                                        Type *baseType1 = pointerType->get_base();
     
    653660
    654661                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    655                         // if this is a polymorphic assignment function, put it in the map for this scope
     662                        // if this is a assignment function, put it in the map for this scope
    656663                        if ( Type *assignedType = isAssignment( functionDecl ) ) {
    657664                                if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
     
    662669                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    663670                                doBeginScope();
    664                                 TyVarMap oldtyVars = scopeTyVars;
    665                                 std::map< std::string, DeclarationWithType *> oldassignOps = assignOps;
     671                                scopeTyVars.beginScope();
     672                                assignOps.beginScope();
    666673                                DeclarationWithType *oldRetval = retval;
    667674                                bool oldUseRetval = useRetval;
     
    704711                                functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
    705712
    706                                 scopeTyVars = oldtyVars;
    707                                 assignOps = oldassignOps;
    708                                 // std::cerr << "end FunctionDecl: ";
    709                                 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    710                                 //      std::cerr << i->first << " ";
    711                                 // }
    712                                 // std::cerr << "\n";
     713                                scopeTyVars.endScope();
     714                                assignOps.endScope();
    713715                                retval = oldRetval;
    714716                                useRetval = oldUseRetval;
     
    743745                }
    744746
    745                 Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
    746                         std::list<Expression*> noDesignators;
    747                         std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
    748 
    749                         // make a new temporary array
    750                         Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    751                         std::stringstream lenGen;
    752                         lenGen << baseMembers.size();
    753                         ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );
    754                         ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );
    755 
    756                         // build initializer list for temporary
    757                         std::list< Initializer* > inits;
    758                         for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
    759                                 DeclarationWithType *memberDecl;
    760                                 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
    761                                         memberDecl = origMember->clone();
    762                                 } else {
    763                                         memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
    764                                 }
    765                                 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ), noDesignators ) );
    766                         }
    767                         arrayTemp->set_init( new ListInit( inits, noDesignators ) );
    768 
    769                         // return variable pointing to temporary
    770                         return new VariableExpr( arrayTemp );
    771                 }
    772 
    773747                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
    774                         Type *polyBase = hasPolyBase( parmType, exprTyVars );
    775                         if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    776                                 std::string sizeName = sizeofName( polyBase );
    777                                 if ( seenTypes.count( sizeName ) ) return;
     748                        Type *polyType = isPolyType( parmType, exprTyVars );
     749                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     750                                std::string typeName = mangleType( polyType );
     751                                if ( seenTypes.count( typeName ) ) return;
    778752
    779753                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
     
    781755                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
    782756                                arg++;
    783                                 if ( dynamic_cast< StructInstType* >( polyBase ) ) {
     757                                if ( dynamic_cast< StructInstType* >( polyType ) ) {
    784758                                        if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
    785                                                 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
    786                                                 arg++;
     759                                                // zero-length arrays are forbidden by C, so don't pass offset for empty struct
     760                                                if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
     761                                                        arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
     762                                                        arg++;
     763                                                }
    787764                                        } else {
    788765                                                throw SemanticError( "Cannot pass non-struct type for generic struct" );
     
    790767                                }
    791768
    792                                 seenTypes.insert( sizeName );
     769                                seenTypes.insert( typeName );
    793770                        }
    794771                }
     
    826803                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
    827804                        }
    828                        
     805
    829806                        // add type information args for presently unseen types in parameter list
    830807                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
     
    905882                        assert( env );
    906883                        Type *concrete = replaceWithConcrete( appExpr, polyType );
    907                         // add out-parameter for return value   
     884                        // add out-parameter for return value
    908885                        return addRetParam( appExpr, function, concrete, arg );
    909886                }
     
    932909                                        return;
    933910                                } else if ( arg->get_results().front()->get_isLvalue() ) {
    934                                         // VariableExpr and MemberExpr are lvalues
    935                                         arg = new AddressExpr( arg );
     911                                        // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
     912                                        if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
     913                                                commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
     914                                        } else {
     915                                                arg = new AddressExpr( arg );
     916                                        }
    936917                                } else {
    937918                                        // use type computed in unification to declare boxed variables
     
    10281009                        } // for
    10291010                }
    1030 
    1031 
    10321011
    10331012                FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     
    11461125                                addAssign->get_args().push_back( appExpr->get_args().front() );
    11471126                        } // if
    1148                         addAssign->get_args().push_back( new NameExpr( sizeofName( polyType ) ) );
     1127                        addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
    11491128                        addAssign->get_results().front() = appExpr->get_results().front()->clone();
    11501129                        if ( appExpr->get_env() ) {
     
    11731152                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    11741153                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1175                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1154                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    11761155                                                        ret->get_args().push_back( appExpr->get_args().front() );
    11771156                                                        ret->get_args().push_back( multiply );
     
    11791158                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    11801159                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    1181                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
     1160                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    11821161                                                        ret->get_args().push_back( multiply );
    11831162                                                        ret->get_args().push_back( appExpr->get_args().back() );
     
    12421221                                                        UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
    12431222                                                        divide->get_args().push_back( appExpr );
    1244                                                         divide->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1223                                                        divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    12451224                                                        divide->get_results().push_front( appExpr->get_results().front()->clone() );
    12461225                                                        if ( appExpr->get_env() ) {
     
    12521231                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    12531232                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1254                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1233                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    12551234                                                        appExpr->get_args().back() = multiply;
    12561235                                                } else if ( baseType2 ) {
    12571236                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    12581237                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    1259                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
     1238                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    12601239                                                        appExpr->get_args().front() = multiply;
    12611240                                                } // if
     
    12671246                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    12681247                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1269                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType ) ) );
     1248                                                        multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
    12701249                                                        appExpr->get_args().back() = multiply;
    12711250                                                } // if
     
    13041283                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    13051284
    1306                         TyVarMap exprTyVars;
     1285                        TyVarMap exprTyVars( (TypeDecl::Kind)-1 );
    13071286                        makeTyVarMap( function, exprTyVars );
    13081287                        ReferenceToType *polyRetType = isPolyRet( function );
     
    13271306
    13281307                        boxParams( appExpr, function, arg, exprTyVars );
    1329 
    13301308                        passAdapters( appExpr, function, exprTyVars );
    13311309
     
    13881366                        return new VariableExpr( functionObj );
    13891367                }
    1390                
     1368
    13911369                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
    13921370                        if ( retval && returnStmt->get_expr() ) {
     
    14071385                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
    14081386                                        // find assignment operator for type variable
    1409                                         std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
     1387                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    14101388                                        if ( assignIter == assignOps.end() ) {
    14111389                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
     
    14291407                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
    14301408                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
    1431                                                 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
    1432 
    1433                                                 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
    1434                                                 assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
    1435                                                 DeclarationWithType *actualDecl = asserts.front();
    1436                                                 TypeInstType *actualType = isTypeInstAssignment( actualDecl );
    1437                                                 assert( actualType && "First assertion of type with assertions should be assignment operator" );
     1409                                                // Add appropriate mapping to assignment expression environment
    14381410                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
    14391411                                                assert( formalTypeExpr && "type parameters must be type expressions" );
    14401412                                                Type *formalType = formalTypeExpr->get_type();
    1441                                                 assignExpr->get_env()->add( actualType->get_name(), formalType );
    1442                                                
     1413                                                assignExpr->get_env()->add( (*forallIt)->get_name(), formalType );
     1414
     1415                                                // skip types with no assign op (ftype/dtype)
     1416                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue;
     1417
     1418                                                // find assignment operator for formal type
    14431419                                                DeclarationWithType *assertAssign = 0;
    14441420                                                if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
    1445                                                         std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
     1421                                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
    14461422                                                        if ( assertAssignIt == assignOps.end() ) {
    14471423                                                                throw SemanticError( "No assignment operation found for ", formalTypeInstType );
     
    14541430                                                        }
    14551431                                                }
    1456                                                
    1457 
     1432
     1433                                                // add inferred parameter for field assignment operator to assignment expression
     1434                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
     1435                                                assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
     1436                                                DeclarationWithType *actualDecl = asserts.front();
    14581437                                                assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
    14591438                                                        = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
     
    14811460
    14821461                Type * Pass1::mutate( PointerType *pointerType ) {
    1483                         TyVarMap oldtyVars = scopeTyVars;
     1462                        scopeTyVars.beginScope();
    14841463                        makeTyVarMap( pointerType, scopeTyVars );
    14851464
    14861465                        Type *ret = Mutator::mutate( pointerType );
    14871466
    1488                         scopeTyVars = oldtyVars;
     1467                        scopeTyVars.endScope();
    14891468                        return ret;
    14901469                }
    14911470
    14921471                Type * Pass1::mutate( FunctionType *functionType ) {
    1493                         TyVarMap oldtyVars = scopeTyVars;
     1472                        scopeTyVars.beginScope();
    14941473                        makeTyVarMap( functionType, scopeTyVars );
    14951474
    14961475                        Type *ret = Mutator::mutate( functionType );
    14971476
    1498                         scopeTyVars = oldtyVars;
     1477                        scopeTyVars.endScope();
    14991478                        return ret;
    15001479                }
     
    15611540
    15621541                Type * Pass2::mutate( PointerType *pointerType ) {
    1563                         TyVarMap oldtyVars = scopeTyVars;
     1542                        scopeTyVars.beginScope();
    15641543                        makeTyVarMap( pointerType, scopeTyVars );
    15651544
    15661545                        Type *ret = Mutator::mutate( pointerType );
    15671546
    1568                         scopeTyVars = oldtyVars;
     1547                        scopeTyVars.endScope();
    15691548                        return ret;
    15701549                }
    15711550
    15721551                Type *Pass2::mutate( FunctionType *funcType ) {
    1573                         TyVarMap oldtyVars = scopeTyVars;
     1552                        scopeTyVars.beginScope();
    15741553                        makeTyVarMap( funcType, scopeTyVars );
    15751554
     
    15881567                        ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
    15891568                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
    1590 //   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
    15911569                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
    15921570                                ObjectDecl *sizeParm, *alignParm;
     
    15941572                                if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
    15951573                                        TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
     1574                                        std::string parmName = mangleType( &parmType );
    15961575
    15971576                                        sizeParm = newObj.clone();
    1598                                         sizeParm->set_name( sizeofName( &parmType ) );
     1577                                        sizeParm->set_name( sizeofName( parmName ) );
    15991578                                        last = funcType->get_parameters().insert( last, sizeParm );
    16001579                                        ++last;
    16011580
    16021581                                        alignParm = newObj.clone();
    1603                                         alignParm->set_name( alignofName( &parmType ) );
     1582                                        alignParm->set_name( alignofName( parmName ) );
    16041583                                        last = funcType->get_parameters().insert( last, alignParm );
    16051584                                        ++last;
     
    16161595                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    16171596                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
    1618                                 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
    1619                                 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    1620                                         std::string sizeName = sizeofName( polyBase );
    1621                                         if ( seenTypes.count( sizeName ) ) continue;
     1597                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1598                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     1599                                        std::string typeName = mangleType( polyType );
     1600                                        if ( seenTypes.count( typeName ) ) continue;
    16221601
    16231602                                        ObjectDecl *sizeParm, *alignParm, *offsetParm;
    16241603                                        sizeParm = newObj.clone();
    1625                                         sizeParm->set_name( sizeName );
     1604                                        sizeParm->set_name( sizeofName( typeName ) );
    16261605                                        last = funcType->get_parameters().insert( last, sizeParm );
    16271606                                        ++last;
    16281607
    16291608                                        alignParm = newObj.clone();
    1630                                         alignParm->set_name( alignofName( polyBase ) );
     1609                                        alignParm->set_name( alignofName( typeName ) );
    16311610                                        last = funcType->get_parameters().insert( last, alignParm );
    16321611                                        ++last;
    16331612
    1634                                         if ( dynamic_cast< StructInstType* >( polyBase ) ) {
    1635                                                 offsetParm = newPtr.clone();
    1636                                                 offsetParm->set_name( offsetofName( polyBase ) );
    1637                                                 last = funcType->get_parameters().insert( last, offsetParm );
    1638                                                 ++last;
     1613                                        if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
     1614                                                // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
     1615                                                if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
     1616                                                        offsetParm = newPtr.clone();
     1617                                                        offsetParm->set_name( offsetofName( typeName ) );
     1618                                                        last = funcType->get_parameters().insert( last, offsetParm );
     1619                                                        ++last;
     1620                                                }
    16391621                                        }
    16401622
    1641                                         seenTypes.insert( sizeName );
     1623                                        seenTypes.insert( typeName );
    16421624                                }
    16431625                        }
     
    16491631                        mutateAll( funcType->get_parameters(), *this );
    16501632
    1651                         scopeTyVars = oldtyVars;
     1633                        scopeTyVars.endScope();
    16521634                        return funcType;
    16531635                }
     
    18421824                }
    18431825
    1844 ////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
     1826////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
     1827
     1828                void PolyGenericCalculator::beginTypeScope( Type *ty ) {
     1829                        scopeTyVars.beginScope();
     1830                        makeTyVarMap( ty, scopeTyVars );
     1831                }
     1832
     1833                void PolyGenericCalculator::endTypeScope() {
     1834                        scopeTyVars.endScope();
     1835                }
    18451836
    18461837                template< typename DeclClass >
    1847                 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
    1848                         TyVarMap oldtyVars = scopeTyVars;
    1849                         makeTyVarMap( type, scopeTyVars );
     1838                DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
     1839                        beginTypeScope( type );
     1840                        knownLayouts.beginScope();
     1841                        knownOffsets.beginScope();
    18501842
    18511843                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    18521844
    1853                         scopeTyVars = oldtyVars;
     1845                        knownOffsets.endScope();
     1846                        knownLayouts.endScope();
     1847                        endTypeScope();
    18541848                        return ret;
    18551849                }
    18561850
    1857                 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
     1851                ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
    18581852                        return handleDecl( objectDecl, objectDecl->get_type() );
    18591853                }
    18601854
    1861                 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
     1855                DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
    18621856                        return handleDecl( functionDecl, functionDecl->get_functionType() );
    18631857                }
    18641858
    1865                 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
     1859                TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
    18661860                        return handleDecl( typedefDecl, typedefDecl->get_base() );
    18671861                }
    18681862
    1869                 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
     1863                TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
    18701864                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    18711865                        return Mutator::mutate( typeDecl );
    18721866                }
    18731867
    1874                 Type * MemberExprFixer::mutate( PointerType *pointerType ) {
    1875                         TyVarMap oldtyVars = scopeTyVars;
    1876                         makeTyVarMap( pointerType, scopeTyVars );
     1868                Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
     1869                        beginTypeScope( pointerType );
    18771870
    18781871                        Type *ret = Mutator::mutate( pointerType );
    18791872
    1880                         scopeTyVars = oldtyVars;
     1873                        endTypeScope();
    18811874                        return ret;
    18821875                }
    18831876
    1884                 Type * MemberExprFixer::mutate( FunctionType *functionType ) {
    1885                         TyVarMap oldtyVars = scopeTyVars;
    1886                         makeTyVarMap( functionType, scopeTyVars );
    1887 
    1888                         Type *ret = Mutator::mutate( functionType );
    1889 
    1890                         scopeTyVars = oldtyVars;
     1877                Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
     1878                        beginTypeScope( funcType );
     1879
     1880                        // make sure that any type information passed into the function is accounted for
     1881                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
     1882                                // condition here duplicates that in Pass2::mutate( FunctionType* )
     1883                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1884                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     1885                                        knownLayouts.insert( mangleType( polyType ) );
     1886                                }
     1887                        }
     1888
     1889                        Type *ret = Mutator::mutate( funcType );
     1890
     1891                        endTypeScope();
    18911892                        return ret;
    18921893                }
    18931894
    1894                 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
     1895                Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
    18951896                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    1896                                 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
     1897                                if ( findGeneric( objectDecl->get_type() ) ) {
    18971898                                        // change initialization of a polymorphic value object
    18981899                                        // to allocate storage with alloca
    18991900                                        Type *declType = objectDecl->get_type();
    19001901                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
    1901                                         alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
     1902                                        alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) );
    19021903
    19031904                                        delete objectDecl->get_init();
     
    19311932                        ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
    19321933                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
    1933                         fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
     1934                        fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
    19341935                        fieldOffset->get_args().push_back( fieldIndex );
    19351936                        return fieldOffset;
     
    19461947                }
    19471948
    1948                 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
     1949                Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
    19491950                        // mutate, exiting early if no longer MemberExpr
    19501951                        Expression *expr = Mutator::mutate( memberExpr );
     
    19631964                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
    19641965                        if ( ! objectType ) return memberExpr;
     1966                        findGeneric( objectType ); // ensure layout for this type is available
    19651967
    19661968                        Expression *newMemberExpr = 0;
     
    19941996                }
    19951997
    1996                 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
     1998                ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
     1999                        ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
     2000                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     2001                        return newObj;
     2002                }
     2003
     2004                void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
     2005                        for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     2006                                if ( findGeneric( *param ) ) {
     2007                                        // push size/align vars for a generic parameter back
     2008                                        std::string paramName = mangleType( *param );
     2009                                        layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
     2010                                        layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
     2011                                } else {
     2012                                        layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
     2013                                        layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
     2014                                }
     2015                        }
     2016                }
     2017
     2018                /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
     2019                bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
     2020                        bool hasDynamicLayout = false;
     2021
     2022                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     2023                        std::list< Expression* >::const_iterator typeParam = typeParams.begin();
     2024                        for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
     2025                                // skip non-otype parameters
     2026                                if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
     2027                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
     2028                                assert( typeExpr && "all otype parameters should be type expressions" );
     2029
     2030                                Type *type = typeExpr->get_type();
     2031                                out.push_back( type );
     2032                                if ( isPolyType( type ) ) hasDynamicLayout = true;
     2033                        }
     2034                        assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
     2035
     2036                        return hasDynamicLayout;
     2037                }
     2038
     2039                bool PolyGenericCalculator::findGeneric( Type *ty ) {
     2040                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
     2041                                // duplicate logic from isPolyType()
     2042                                if ( env ) {
     2043                                        if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
     2044                                                return findGeneric( newType );
     2045                                        } // if
     2046                                } // if
     2047                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     2048                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
     2049                                        return true;
     2050                                }
     2051                                return false;
     2052                        } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
     2053                                // check if this type already has a layout generated for it
     2054                                std::string typeName = mangleType( ty );
     2055                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2056
     2057                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2058                                std::list< Type* > otypeParams;
     2059                                if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
     2060
     2061                                // insert local variables for layout and generate call to layout function
     2062                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2063                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2064
     2065                                int n_members = structTy->get_baseStruct()->get_members().size();
     2066                                if ( n_members == 0 ) {
     2067                                        // all empty structs have the same layout - size 1, align 1
     2068                                        makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2069                                        makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2070                                        // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
     2071                                } else {
     2072                                        ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2073                                        ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2074                                        ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
     2075
     2076                                        // generate call to layout function
     2077                                        UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
     2078                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2079                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2080                                        layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
     2081                                        addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2082
     2083                                        stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2084                                }
     2085
     2086                                return true;
     2087                        } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
     2088                                // check if this type already has a layout generated for it
     2089                                std::string typeName = mangleType( ty );
     2090                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2091
     2092                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2093                                std::list< Type* > otypeParams;
     2094                                if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
     2095
     2096                                // insert local variables for layout and generate call to layout function
     2097                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2098                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2099
     2100                                ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2101                                ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2102
     2103                                // generate call to layout function
     2104                                UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
     2105                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2106                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2107                                addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2108
     2109                                stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2110
     2111                                return true;
     2112                        }
     2113
     2114                        return false;
     2115                }
     2116
     2117                Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
     2118                        Type *ty = sizeofExpr->get_type();
     2119                        if ( findGeneric( ty ) ) {
     2120                                Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) );
     2121                                delete sizeofExpr;
     2122                                return ret;
     2123                        }
     2124                        return sizeofExpr;
     2125                }
     2126
     2127                Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
     2128                        Type *ty = alignofExpr->get_type();
     2129                        if ( findGeneric( ty ) ) {
     2130                                Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
     2131                                delete alignofExpr;
     2132                                return ret;
     2133                        }
     2134                        return alignofExpr;
     2135                }
     2136
     2137                Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
    19972138                        // mutate, exiting early if no longer OffsetofExpr
    19982139                        Expression *expr = Mutator::mutate( offsetofExpr );
     
    20012142
    20022143                        // only mutate expressions for polymorphic structs/unions
    2003                         Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
    2004                         if ( ! ty ) return offsetofExpr;
     2144                        Type *ty = offsetofExpr->get_type();
     2145                        if ( ! findGeneric( ty ) ) return offsetofExpr;
    20052146
    20062147                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
     
    20192160                }
    20202161
     2162                Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
     2163                        StructInstType *ty = offsetPackExpr->get_type();
     2164
     2165                        Expression *ret = 0;
     2166                        if ( findGeneric( ty ) ) {
     2167                                // pull offset back from generated type information
     2168                                ret = new NameExpr( offsetofName( mangleType( ty ) ) );
     2169                        } else {
     2170                                std::string offsetName = offsetofName( mangleType( ty ) );
     2171                                if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     2172                                        // use the already-generated offsets for this type
     2173                                        ret = new NameExpr( offsetName );
     2174                                } else {
     2175                                        knownOffsets.insert( offsetName );
     2176
     2177                                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
     2178                                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2179
     2180                                        // build initializer list for offset array
     2181                                        std::list< Initializer* > inits;
     2182                                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
     2183                                                DeclarationWithType *memberDecl;
     2184                                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
     2185                                                        memberDecl = origMember->clone();
     2186                                                } else {
     2187                                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
     2188                                                }
     2189                                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
     2190                                        }
     2191
     2192                                        // build the offset array and replace the pack with a reference to it
     2193                                        ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
     2194                                                        new ListInit( inits ) );
     2195                                        ret = new VariableExpr( offsetArray );
     2196                                }
     2197                        }
     2198
     2199                        delete offsetPackExpr;
     2200                        return ret;
     2201                }
     2202
     2203                void PolyGenericCalculator::doBeginScope() {
     2204                        knownLayouts.beginScope();
     2205                        knownOffsets.beginScope();
     2206                }
     2207
     2208                void PolyGenericCalculator::doEndScope() {
     2209                        knownLayouts.endScope();
     2210                        knownOffsets.endScope();
     2211                }
     2212
    20212213////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    20222214
    20232215                template< typename DeclClass >
    20242216                DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
    2025                         TyVarMap oldtyVars = scopeTyVars;
     2217                        scopeTyVars.beginScope();
    20262218                        makeTyVarMap( type, scopeTyVars );
    20272219
     
    20292221                        ScrubTyVars::scrub( decl, scopeTyVars );
    20302222
    2031                         scopeTyVars = oldtyVars;
     2223                        scopeTyVars.endScope();
    20322224                        return ret;
    20332225                }
     
    20592251
    20602252                Type * Pass3::mutate( PointerType *pointerType ) {
    2061                         TyVarMap oldtyVars = scopeTyVars;
     2253                        scopeTyVars.beginScope();
    20622254                        makeTyVarMap( pointerType, scopeTyVars );
    20632255
    20642256                        Type *ret = Mutator::mutate( pointerType );
    20652257
    2066                         scopeTyVars = oldtyVars;
     2258                        scopeTyVars.endScope();
    20672259                        return ret;
    20682260                }
    20692261
    20702262                Type * Pass3::mutate( FunctionType *functionType ) {
    2071                         TyVarMap oldtyVars = scopeTyVars;
     2263                        scopeTyVars.beginScope();
    20722264                        makeTyVarMap( functionType, scopeTyVars );
    20732265
    20742266                        Type *ret = Mutator::mutate( functionType );
    20752267
    2076                         scopeTyVars = oldtyVars;
     2268                        scopeTyVars.endScope();
    20772269                        return ret;
    20782270                }
  • src/GenPoly/FindFunction.cc

    rdb4ecc5 r70a06f6  
    5555                        TyVarMap::iterator var = tyVars.find( (*i)->get_name() );
    5656                        if ( var != tyVars.end() ) {
    57                                 tyVars.erase( var );
     57                                tyVars.erase( var->first );
    5858                        } // if
    5959                } // for
     
    6161
    6262        Type * FindFunction::mutate( FunctionType *functionType ) {
    63                 TyVarMap oldTyVars = tyVars;
     63                tyVars.beginScope();
    6464                handleForall( functionType->get_forall() );
    6565                mutateAll( functionType->get_returnVals(), *this );
     
    7272                        } // if
    7373                } // if
    74                 tyVars = oldTyVars;
     74                tyVars.endScope();
    7575                return ret;
    7676        }
    7777
    7878        Type * FindFunction::mutate( PointerType *pointerType ) {
    79                 TyVarMap oldTyVars = tyVars;
     79                tyVars.beginScope();
    8080                handleForall( pointerType->get_forall() );
    8181                Type *ret = Mutator::mutate( pointerType );
    82                 tyVars = oldTyVars;
     82                tyVars.endScope();
    8383                return ret;
    8484        }
  • src/GenPoly/GenPoly.cc

    rdb4ecc5 r70a06f6  
    1616#include "GenPoly.h"
    1717
    18 #include "SymTab/Mangler.h"
    1918#include "SynTree/Expression.h"
    2019#include "SynTree/Type.h"
     
    3837        ReferenceToType *isPolyRet( FunctionType *function ) {
    3938                if ( ! function->get_returnVals().empty() ) {
    40                         TyVarMap forallTypes;
     39                        TyVarMap forallTypes( (TypeDecl::Kind)-1 );
    4140                        makeTyVarMap( function, forallTypes );
    4241                        return (ReferenceToType*)isPolyType( function->get_returnVals().front()->get_type(), forallTypes );
     
    218217        }
    219218
    220         std::string sizeofName( Type *ty ) {
    221                 return std::string( "_sizeof_" ) + SymTab::Mangler::mangleType( ty );
    222         }
    223 
    224         std::string alignofName( Type *ty ) {
    225                 return std::string( "_alignof_" ) + SymTab::Mangler::mangleType( ty );
    226         }
    227 
    228         std::string offsetofName( Type* ty ) {
    229                 return std::string( "_offsetof_" ) + SymTab::Mangler::mangleType( ty );
    230         }
    231 
    232219} // namespace GenPoly
    233220
  • src/GenPoly/GenPoly.h

    rdb4ecc5 r70a06f6  
    1717#define GENPOLY_H
    1818
    19 #include <map>
    2019#include <string>
    2120#include <iostream>
    2221#include <utility>
     22
     23#include "ErasableScopedMap.h"
     24
     25#include "SymTab/Mangler.h"
    2326
    2427#include "SynTree/Declaration.h"
     
    2730
    2831namespace GenPoly {
    29         typedef std::map< std::string, TypeDecl::Kind > TyVarMap;
     32        typedef ErasableScopedMap< std::string, TypeDecl::Kind > TyVarMap;
    3033
    3134        /// A function needs an adapter if it returns a polymorphic value or if any of its
     
    6972        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
    7073
    71         /// Gets the name of the sizeof parameter for the type
    72         std::string sizeofName( Type *ty );
     74        /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
     75        inline std::string mangleType( Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
     76       
     77        /// Gets the name of the sizeof parameter for the type, given its mangled name
     78        inline std::string sizeofName( const std::string &name ) { return std::string( "_sizeof_" ) + name; }
    7379
    74         /// Gets the name of the alignof parameter for the type
    75         std::string alignofName( Type *ty );
     80        /// Gets the name of the alignof parameter for the type, given its mangled name
     81        inline std::string alignofName( const std::string &name ) { return std::string( "_alignof_" ) + name; }
    7682
    77         /// Gets the name of the offsetof parameter for the type
    78         std::string offsetofName( Type *ty );
     83        /// Gets the name of the offsetof parameter for the type, given its mangled name
     84        inline std::string offsetofName( const std::string &name ) { return std::string( "_offsetof_" ) + name; }
     85
     86        /// Gets the name of the layout function for a given aggregate type, given its declaration
     87        inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
     88       
    7989} // namespace GenPoly
    8090
  • src/GenPoly/Lvalue.cc

    rdb4ecc5 r70a06f6  
    1717
    1818#include "Lvalue.h"
     19
     20#include "GenPoly.h"
    1921
    2022#include "SynTree/Declaration.h"
     
    6365
    6466        namespace {
    65                 bool isLvalueRet( FunctionType *function ) {
    66                         if ( ! function->get_returnVals().empty() ) {
    67                                 return function->get_returnVals().front()->get_type()->get_isLvalue();
    68                         } else {
    69                                 return false;
    70                         } // if
     67                Type* isLvalueRet( FunctionType *function ) {
     68                        if ( function->get_returnVals().empty() ) return 0;
     69                        Type *ty = function->get_returnVals().front()->get_type();
     70                        return ty->get_isLvalue() ? ty : 0;
    7171                }
    7272
     
    107107                        assert( function );
    108108
    109                         std::string typeName;
    110                         if ( isLvalueRet( function ) && ! isIntrinsicApp( appExpr ) ) {
     109                        Type *funType = isLvalueRet( function );
     110                        if ( funType && ! isIntrinsicApp( appExpr ) ) {
     111                                Expression *expr = appExpr;
     112                                Type *appType = appExpr->get_results().front();
     113                                if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
     114                                        // make sure cast for polymorphic type is inside dereference
     115                                        expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
     116                                }
    111117                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    112                                 deref->get_results().push_back( appExpr->get_results().front() );
    113                                 appExpr->get_results().front() = new PointerType( Type::Qualifiers(), deref->get_results().front()->clone() );
    114                                 deref->get_args().push_back( appExpr );
     118                                deref->get_results().push_back( appType->clone() );
     119                                appExpr->get_results().front() = new PointerType( Type::Qualifiers(), appType );
     120                                deref->get_args().push_back( expr );
    115121                                return deref;
    116122                        } else {
  • src/GenPoly/PolyMutator.cc

    rdb4ecc5 r70a06f6  
    2727        }
    2828
    29         PolyMutator::PolyMutator() : env( 0 ) {
    30         }
     29        PolyMutator::PolyMutator() : scopeTyVars( (TypeDecl::Kind)-1 ), env( 0 ) {}
    3130
    3231        void PolyMutator::mutateStatementList( std::list< Statement* > &statements ) {
  • src/GenPoly/ScopedMap.h

    rdb4ecc5 r70a06f6  
    1717#define _SCOPEDMAP_H
    1818
     19#include <cassert>
    1920#include <iterator>
    2021#include <map>
     
    5051                        typedef typename scope_list::size_type size_type;
    5152
     53                        /// Checks if this iterator points to a valid item
     54                        bool is_valid() const {
     55                                return it != (*scopes)[i].end();
     56                        }
     57
     58                        /// Increments on invalid
     59                        iterator& next_valid() {
     60                                if ( ! is_valid() ) { ++(*this); }
     61                                return *this;
     62                        }
     63
     64                        /// Decrements on invalid
     65                        iterator& prev_valid() {
     66                                if ( ! is_valid() ) { --(*this); }
     67                                return *this;
     68                        }
     69
    5270                        iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
    5371                                : scopes(&_scopes), it(_it), i(_i) {}
     
    6785                                        --i;
    6886                                        it = (*scopes)[i].begin();
    69                                         return *this;
    70                                 }
    71                                 ++it;
    72                                 return *this;
     87                                } else {
     88                                        ++it;
     89                                }
     90                                return next_valid();
    7391                        }
    7492                        iterator& operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     
    8199                                }
    82100                                --it;
    83                                 return *this;
     101                                return prev_valid();
    84102                        }
    85103                        iterator& operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     
    104122                        typedef typename scope_list::size_type size_type;
    105123
     124                        /// Checks if this iterator points to a valid item
     125                        bool is_valid() const {
     126                                return it != (*scopes)[i].end();
     127                        }
     128
     129                        /// Increments on invalid
     130                        const_iterator& next_valid() {
     131                                if ( ! is_valid() ) { ++(*this); }
     132                                return *this;
     133                        }
     134
     135                        /// Decrements on invalid
     136                        const_iterator& prev_valid() {
     137                                if ( ! is_valid() ) { --(*this); }
     138                                return *this;
     139                        }
     140
    106141                        const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
    107142                                : scopes(&_scopes), it(_it), i(_i) {}
     
    126161                                        --i;
    127162                                        it = (*scopes)[i].begin();
    128                                         return *this;
    129                                 }
    130                                 ++it;
    131                                 return *this;
     163                                } else {
     164                                        ++it;
     165                                }
     166                                return next_valid();
    132167                        }
    133168                        const_iterator& operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     
    140175                                }
    141176                                --it;
    142                                 return *this;
     177                                return prev_valid();
    143178                        }
    144179                        const_iterator& operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     
    164199                void endScope() {
    165200                        scopes.pop_back();
     201                        assert( ! scopes.empty() );
    166202                }
    167203
     
    169205                ScopedMap() { beginScope(); }
    170206
    171                 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1); }
    172                 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1); }
    173                 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1); }
     207                iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     208                const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     209                const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    174210                iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    175211                const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     
    188224                        return end();
    189225                }
    190                 const_iterator find( const Key &key ) const { return const_iterator( find( key ) ); }
     226                const_iterator find( const Key &key ) const {
     227                                return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->find( key ) );
     228                }
    191229               
    192230                /// Finds the given key in the outermost scope inside the given scope where it occurs
     
    200238                        return end();
    201239                }
    202                 const_iterator findNext( const_iterator &it, const Key &key ) const { return const_iterator( findNext( it, key ) ); }
     240                const_iterator findNext( const_iterator &it, const Key &key ) const {
     241                                return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findNext( it, key ) );
     242                }
    203243
    204244                /// Inserts the given key-value pair into the outermost scope
     
    208248                }
    209249                std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    210                
     250
     251                Value& operator[] ( const Key &key ) {
     252                        iterator slot = find( key );
     253                        if ( slot != end() ) return slot->second;
     254                        return insert( key, Value() ).first->second;
     255                }
    211256        };
    212257} // namespace GenPoly
  • src/GenPoly/ScrubTyVars.cc

    rdb4ecc5 r70a06f6  
    6464                // sizeof( T ) => _sizeof_T parameter, which is the size of T
    6565                if ( Type *polyType = isPolyType( szeof->get_type() ) ) {
    66                         Expression *expr = new NameExpr( sizeofName( polyType ) );
     66                        Expression *expr = new NameExpr( sizeofName( mangleType( polyType ) ) );
    6767                        return expr;
    6868                } else {
     
    7474                // alignof( T ) => _alignof_T parameter, which is the alignment of T
    7575                if ( Type *polyType = isPolyType( algnof->get_type() ) ) {
    76                         Expression *expr = new NameExpr( alignofName( polyType ) );
     76                        Expression *expr = new NameExpr( alignofName( mangleType( polyType ) ) );
    7777                        return expr;
    7878                } else {
Note: See TracChangeset for help on using the changeset viewer.