Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rc29d9ce r9799ec8  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Box.cc -- 
     7// Box.cc --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Aug 11 16:22:35 2015
    13 // Update Count     : 89
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jun 29 21:43:03 2016
     13// Update Count     : 296
    1414//
    1515
     16#include <algorithm>
     17#include <iterator>
     18#include <list>
     19#include <map>
    1620#include <set>
    1721#include <stack>
    1822#include <string>
    19 #include <iterator>
    20 #include <algorithm>
     23#include <utility>
     24#include <vector>
    2125#include <cassert>
    2226
    2327#include "Box.h"
     28#include "DeclMutator.h"
    2429#include "PolyMutator.h"
    2530#include "FindFunction.h"
     31#include "ScopedMap.h"
     32#include "ScopedSet.h"
    2633#include "ScrubTyVars.h"
    2734
    2835#include "Parser/ParseNode.h"
    2936
    30 #include "SynTree/Type.h"
     37#include "SynTree/Constant.h"
     38#include "SynTree/Declaration.h"
    3139#include "SynTree/Expression.h"
    3240#include "SynTree/Initializer.h"
     41#include "SynTree/Mutator.h"
    3342#include "SynTree/Statement.h"
    34 #include "SynTree/Mutator.h"
     43#include "SynTree/Type.h"
     44#include "SynTree/TypeSubstitution.h"
    3545
    3646#include "ResolvExpr/TypeEnvironment.h"
    37 
     47#include "ResolvExpr/TypeMap.h"
     48#include "ResolvExpr/typeops.h"
     49
     50#include "SymTab/Indexer.h"
    3851#include "SymTab/Mangler.h"
    3952
    40 #include "SemanticError.h"
    41 #include "UniqueName.h"
    42 #include "utility.h"
     53#include "Common/SemanticError.h"
     54#include "Common/UniqueName.h"
     55#include "Common/utility.h"
    4356
    4457#include <ext/functional> // temporary
     
    4861                const std::list<Label> noLabels;
    4962
     63                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
     64
     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 ) ) {}
     73
     74                        /// Extracts types from a list of TypeExpr*
     75                        TypeList( const std::list< TypeExpr* >& _params ) : params() {
     76                                for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
     77                                        params.push_back( (*param)->get_type()->clone() );
     78                                }
     79                        }
     80
     81                        TypeList& operator= ( const TypeList &that ) {
     82                                deleteAll( params );
     83
     84                                params.clear();
     85                                cloneAll( that.params, params );
     86
     87                                return *this;
     88                        }
     89
     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;
     102
     103                                SymTab::Indexer dummy;
     104                                for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
     105                                        if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
     106                                }
     107                                return true;
     108                        }
     109
     110                        std::list< Type* > params;  ///< Instantiation parameters
     111                };
     112
     113                /// Maps a key and a TypeList to the some value, accounting for scope
     114                template< typename Key, typename Value >
     115                class InstantiationMap {
     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
     124
     125                public:
     126                        /// Starts a new scope
     127                        void beginScope() { instantiations.beginScope(); }
     128
     129                        /// Ends a scope
     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;
     140                                        }
     141                                }
     142                                // no matching instantiations found
     143                                return 0;
     144                        }
     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                        }
     150                };
     151
     152                /// Adds layout-generation functions to polymorphic types
     153                class LayoutFunctionBuilder : public DeclMutator {
     154                        unsigned int functionNesting;  // current level of nested functions
     155                public:
     156                        LayoutFunctionBuilder() : functionNesting( 0 ) {}
     157
     158                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
     159                        virtual Declaration *mutate( StructDecl *structDecl );
     160                        virtual Declaration *mutate( UnionDecl *unionDecl );
     161                };
     162
     163                /// 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
    50164                class Pass1 : public PolyMutator {
    51165                  public:
     
    58172                        virtual Expression *mutate( CommaExpr *commaExpr );
    59173                        virtual Expression *mutate( ConditionalExpr *condExpr );
    60                         virtual Statement *mutate(ReturnStmt *catchStmt);
     174                        virtual Statement * mutate( ReturnStmt *returnStmt );
    61175                        virtual Type *mutate( PointerType *pointerType );
    62                         virtual Type *mutate( FunctionType *pointerType );
    63  
     176                        virtual Type * mutate( FunctionType *functionType );
     177
    64178                        virtual void doBeginScope();
    65179                        virtual void doEndScope();
    66180                  private:
    67                         void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     181                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
     182                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
     183                        /// passes extra type parameters into a polymorphic function application
     184                        void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     185                        /// wraps a function application with a new temporary for the out-parameter return value
    68186                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
    69                         Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg );
     187                        /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
     188                        void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
     189                        /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
     190                        /// If `doClone` is set to false, will not clone interior types
     191                        Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
     192                        /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
     193                        Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
    70194                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    71195                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
    72196                        void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    73197                        void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
    74                         void findAssignOps( const std::list< TypeDecl *> &forall );
     198                        /// Stores assignment operators from assertion list in local map of assignment operations
     199                        void findTypeOps( const std::list< TypeDecl *> &forall );
    75200                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    76201                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
     202                        /// Replaces intrinsic operator functions with their arithmetic desugaring
    77203                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
     204                        /// Inserts a new temporary variable into the current scope with an auto-generated name
    78205                        ObjectDecl *makeTemporary( Type *type );
    79206
    80                         typedef std::map< std::string, FunctionDecl *> AdapterMap;
    81                         std::map< std::string, DeclarationWithType *> assignOps;
    82                         std::stack< AdapterMap > adapters;
     207                        ScopedMap< std::string, DeclarationWithType* > assignOps;    ///< Currently known type variable assignment operators
     208                        ScopedMap< std::string, DeclarationWithType* > ctorOps;      ///< Currently known type variable constructors
     209                        ScopedMap< std::string, DeclarationWithType* > copyOps;      ///< Currently known type variable copy constructors
     210                        ScopedMap< std::string, DeclarationWithType* > dtorOps;      ///< Currently known type variable destructors
     211                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
     212                        ResolvExpr::TypeMap< DeclarationWithType > scopedCtorOps;    ///< Currently known assignment operators
     213                        ResolvExpr::TypeMap< DeclarationWithType > scopedCopyOps;    ///< Currently known assignment operators
     214                        ResolvExpr::TypeMap< DeclarationWithType > scopedDtorOps;    ///< Currently known assignment operators
     215                        ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
     216
    83217                        DeclarationWithType *retval;
    84218                        bool useRetval;
     
    86220                };
    87221
     222                /// * Moves polymorphic returns in function types to pointer-type parameters
     223                /// * adds type size and assertion parameters to parameter lists
    88224                class Pass2 : public PolyMutator {
    89225                  public:
    90                         Pass2();
    91226                        template< typename DeclClass >
    92227                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    97232                        virtual Type *mutate( PointerType *pointerType );
    98233                        virtual Type *mutate( FunctionType *funcType );
     234
    99235                  private:
    100236                        void addAdapters( FunctionType *functionType );
    101  
     237
    102238                        std::map< UniqueId, std::string > adapterName;
    103239                };
    104240
    105                 class Pass3 : public PolyMutator {
    106                   public:
     241                /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     242                class GenericInstantiator : public DeclMutator {
     243                        /// Map of (generic type, parameter list) pairs to concrete type instantiations
     244                        InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
     245                        /// Namer for concrete types
     246                        UniqueName typeNamer;
     247
     248                public:
     249                        GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
     250
     251                        virtual Type* mutate( StructInstType *inst );
     252                        virtual Type* mutate( UnionInstType *inst );
     253
     254        //              virtual Expression* mutate( MemberExpr *memberExpr );
     255
     256                        virtual void doBeginScope();
     257                        virtual void doEndScope();
     258                private:
     259                        /// Wrap instantiation lookup for structs
     260                        StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
     261                        /// Wrap instantiation lookup for unions
     262                        UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
     263                        /// Wrap instantiation insertion for structs
     264                        void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
     265                        /// Wrap instantiation insertion for unions
     266                        void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
     267                };
     268
     269                /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
     270                /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
     271                /// * Calculates polymorphic offsetof expressions from offset array
     272                /// * Inserts dynamic calculation of polymorphic type layouts where needed
     273                class PolyGenericCalculator : public PolyMutator {
     274                public:
    107275                        template< typename DeclClass >
    108276                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    114282                        virtual Type *mutate( PointerType *pointerType );
    115283                        virtual Type *mutate( FunctionType *funcType );
     284                        virtual Expression *mutate( MemberExpr *memberExpr );
     285                        virtual Expression *mutate( SizeofExpr *sizeofExpr );
     286                        virtual Expression *mutate( AlignofExpr *alignofExpr );
     287                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
     288                        virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
     289
     290                        virtual void doBeginScope();
     291                        virtual void doEndScope();
     292
     293                private:
     294                        /// Makes a new variable in the current scope with the given name, type & optional initializer
     295                        ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
     296                        /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
     297                        bool findGeneric( Type *ty );
     298                        /// adds type parameters to the layout call; will generate the appropriate parameters if needed
     299                        void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
     300
     301                        /// Enters a new scope for type-variables, adding the type variables from ty
     302                        void beginTypeScope( Type *ty );
     303                        /// Exits the type-variable scope
     304                        void endTypeScope();
     305
     306                        ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
     307                        ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
     308                };
     309
     310                /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
     311                class Pass3 : public PolyMutator {
     312                  public:
     313                        template< typename DeclClass >
     314                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     315                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
     316                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
     317                        virtual TypedefDecl *mutate( TypedefDecl *objectDecl );
     318                        virtual TypeDecl *mutate( TypeDecl *objectDecl );
     319                        virtual Type *mutate( PointerType *pointerType );
     320                        virtual Type *mutate( FunctionType *funcType );
    116321                  private:
    117322                };
     
    119324        } // anonymous namespace
    120325
    121         void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {
    122                 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    123                         if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {
    124                                 (*i)->print( os );
    125                                 os << std::endl;
    126                         } // if
     326        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
     327        template< typename MutatorType >
     328        inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
     329                bool seenIntrinsic = false;
     330                SemanticError errors;
     331                for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     332                        try {
     333                                if ( *i ) {
     334                                        if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
     335                                                seenIntrinsic = true;
     336                                        } else if ( seenIntrinsic ) {
     337                                                seenIntrinsic = false; // break on this line when debugging for end of prelude
     338                                        }
     339
     340                                        *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
     341                                        assert( *i );
     342                                } // if
     343                        } catch( SemanticError &e ) {
     344                                errors.append( e );
     345                        } // try
    127346                } // for
     347                if ( ! errors.isEmpty() ) {
     348                        throw errors;
     349                } // if
    128350        }
    129351
    130352        void box( std::list< Declaration *>& translationUnit ) {
     353                LayoutFunctionBuilder layoutBuilder;
    131354                Pass1 pass1;
    132355                Pass2 pass2;
     356                GenericInstantiator instantiator;
     357                PolyGenericCalculator polyCalculator;
    133358                Pass3 pass3;
    134                 mutateAll( translationUnit, pass1 );
    135                 mutateAll( translationUnit, pass2 );
    136                 mutateAll( translationUnit, pass3 );
     359
     360                layoutBuilder.mutateDeclarationList( translationUnit );
     361                mutateTranslationUnit/*All*/( translationUnit, pass1 );
     362                mutateTranslationUnit/*All*/( translationUnit, pass2 );
     363                instantiator.mutateDeclarationList( translationUnit );
     364                mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
     365                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    137366        }
    138367
     368        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     369
     370        DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
     371                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     372                mutateAll( functionDecl->get_oldDecls(), *this );
     373                ++functionNesting;
     374                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     375                --functionNesting;
     376                return functionDecl;
     377        }
     378
     379        /// Get a list of type declarations that will affect a layout function
     380        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
     381                std::list< TypeDecl * > otypeDecls;
     382
     383                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     384                        if ( (*decl)->get_kind() == TypeDecl::Any ) {
     385                                otypeDecls.push_back( *decl );
     386                        }
     387                }
     388
     389                return otypeDecls;
     390        }
     391
     392        /// Adds parameters for otype layout to a function type
     393        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
     394                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     395
     396                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     397                        TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
     398                        std::string paramName = mangleType( &paramType );
     399                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     400                        layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     401                }
     402        }
     403
     404        /// Builds a layout function declaration
     405        FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {
     406                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     407                // because each unit generates copies of the default routines for each aggregate.
     408                FunctionDecl *layoutDecl = new FunctionDecl(
     409                        layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
     410                layoutDecl->fixUniqueId();
     411                return layoutDecl;
     412        }
     413
     414        /// Makes a unary operation
     415        Expression *makeOp( const std::string &name, Expression *arg ) {
     416                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     417                expr->get_args().push_back( arg );
     418                return expr;
     419        }
     420
     421        /// Makes a binary operation
     422        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
     423                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     424                expr->get_args().push_back( lhs );
     425                expr->get_args().push_back( rhs );
     426                return expr;
     427        }
     428
     429        /// Returns the dereference of a local pointer variable
     430        Expression *derefVar( ObjectDecl *var ) {
     431                return makeOp( "*?", new VariableExpr( var ) );
     432        }
     433
     434        /// makes an if-statement with a single-expression if-block and no then block
     435        Statement *makeCond( Expression *cond, Expression *ifPart ) {
     436                return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
     437        }
     438
     439        /// makes a statement that assigns rhs to lhs if lhs < rhs
     440        Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
     441                return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
     442        }
     443
     444        /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
     445        Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
     446                // check that the lhs is zeroed out to the level of rhs
     447                Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
     448                // if not aligned, increment to alignment
     449                Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
     450                return makeCond( ifCond, ifExpr );
     451        }
     452
     453        /// adds an expression to a compound statement
     454        void addExpr( CompoundStmt *stmts, Expression *expr ) {
     455                stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
     456        }
     457
     458        /// adds a statement to a compound statement
     459        void addStmt( CompoundStmt *stmts, Statement *stmt ) {
     460                stmts->get_kids().push_back( stmt );
     461        }
     462
     463        Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
     464                // do not generate layout function for "empty" tag structs
     465                if ( structDecl->get_members().empty() ) return structDecl;
     466
     467                // get parameters that can change layout, exiting early if none
     468                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
     469                if ( otypeParams.empty() ) return structDecl;
     470
     471                // build layout function signature
     472                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     473                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     474                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     475
     476                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     477                layoutFnType->get_parameters().push_back( sizeParam );
     478                ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     479                layoutFnType->get_parameters().push_back( alignParam );
     480                ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     481                layoutFnType->get_parameters().push_back( offsetParam );
     482                addOtypeParams( layoutFnType, otypeParams );
     483
     484                // build function decl
     485                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );
     486
     487                // calculate struct layout in function body
     488
     489                // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
     490                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
     491                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     492                unsigned long n_members = 0;
     493                bool firstMember = true;
     494                for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
     495                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     496                        assert( dwt );
     497                        Type *memberType = dwt->get_type();
     498
     499                        if ( firstMember ) {
     500                                firstMember = false;
     501                        } else {
     502                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
     503                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
     504                        }
     505
     506                        // place current size in the current offset index
     507                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ),
     508                                                                              derefVar( sizeParam ) ) );
     509                        ++n_members;
     510
     511                        // add member size to current size
     512                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     513
     514                        // take max of member alignment and global alignment
     515                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     516                }
     517                // make sure the type is end-padded to a multiple of its alignment
     518                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     519
     520                addDeclarationAfter( layoutDecl );
     521                return structDecl;
     522        }
     523
     524        Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
     525                // do not generate layout function for "empty" tag unions
     526                if ( unionDecl->get_members().empty() ) return unionDecl;
     527
     528                // get parameters that can change layout, exiting early if none
     529                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
     530                if ( otypeParams.empty() ) return unionDecl;
     531
     532                // build layout function signature
     533                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     534                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     535                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     536
     537                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     538                layoutFnType->get_parameters().push_back( sizeParam );
     539                ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     540                layoutFnType->get_parameters().push_back( alignParam );
     541                addOtypeParams( layoutFnType, otypeParams );
     542
     543                // build function decl
     544                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );
     545
     546                // calculate union layout in function body
     547                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     548                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     549                for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
     550                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     551                        assert( dwt );
     552                        Type *memberType = dwt->get_type();
     553
     554                        // take max member size and global size
     555                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     556
     557                        // take max of member alignment and global alignment
     558                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     559                }
     560                // make sure the type is end-padded to a multiple of its alignment
     561                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     562
     563                addDeclarationAfter( layoutDecl );
     564                return unionDecl;
     565        }
     566
    139567        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    140568
    141569        namespace {
     570                std::string makePolyMonoSuffix( FunctionType * function, const TyVarMap &tyVars ) {
     571                        std::stringstream name;
     572
     573                        // NOTE: this function previously used isPolyObj, which failed to produce
     574                        // the correct thing in some situations. It's not clear to me why this wasn't working.
     575
     576                        // if the return type or a parameter type involved polymorphic types, then the adapter will need
     577                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
     578                        // with the same mangled name, so we need to further mangle the names.
     579                        for ( std::list< DeclarationWithType *>::iterator retval = function->get_returnVals().begin(); retval != function->get_returnVals().end(); ++retval ) {
     580                                if ( isPolyType( (*retval)->get_type(), tyVars ) ) {
     581                                        name << "P";
     582                                } else {
     583                                        name << "M";
     584                                }
     585                        }
     586                        name << "_";
     587                        std::list< DeclarationWithType *> &paramList = function->get_parameters();
     588                        for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
     589                                if ( isPolyType( (*arg)->get_type(), tyVars ) ) {
     590                                        name << "P";
     591                                } else {
     592                                        name << "M";
     593                                }
     594                        } // for
     595                        return name.str();
     596                }
     597
     598                std::string mangleAdapterName( FunctionType * function, const TyVarMap &tyVars ) {
     599                        return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars );
     600                }
     601
    142602                std::string makeAdapterName( const std::string &mangleName ) {
    143603                        return "_adapter" + mangleName;
    144604                }
    145605
    146                 bool isPolyRet( FunctionType *function, std::string &name, const TyVarMap &otherTyVars ) {
    147                         bool doTransform = false;
    148                         if ( ! function->get_returnVals().empty() ) {
    149                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( function->get_returnVals().front()->get_type() ) ) {
    150        
    151                                         // figure out if the return type is specified by a type parameter
    152                                         for ( std::list< TypeDecl *>::const_iterator tyVar = function->get_forall().begin(); tyVar != function->get_forall().end(); ++tyVar ) {
    153                                                 if ( (*tyVar)->get_name() == typeInst->get_name() ) {
    154                                                         doTransform = true;
    155                                                         name = typeInst->get_name();
    156                                                         break;
     606                Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
     607
     608                /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise
     609                TypeInstType *isTypeInstPtrFn( DeclarationWithType *decl ) {
     610                        if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     611                                if ( funType->get_parameters().size() == 1 ) {
     612                                        if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
     613                                                if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
     614                                                        return refType;
    157615                                                } // if
    158                                         } // for
    159                                         if ( ! doTransform && otherTyVars.find( typeInst->get_name() ) != otherTyVars.end() ) {
    160                                                 doTransform = true;
    161616                                        } // if
    162617                                } // if
    163618                        } // if
    164                         return doTransform;
    165                 }
    166 
    167                 bool isPolyRet( FunctionType *function, std::string &name ) {
    168                         TyVarMap dummyTyVars;
    169                         return isPolyRet( function, name, dummyTyVars );
    170                 }
    171 
    172                 bool isPolyRet( FunctionType *function, const TyVarMap &otherTyVars ) {
    173                         std::string dummyString;
    174                         return isPolyRet( function, dummyString, otherTyVars );
    175                 }
    176 
    177                 Pass1::Pass1()
    178                         : useRetval( false ), tempNamer( "_temp" ) {
    179                 }
    180 
    181                 bool checkAssignment( DeclarationWithType *decl, std::string &name ) {
    182                         if ( decl->get_name() == "?=?" ) {
    183                                 if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) {
    184                                         if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) {
    185                                                 if ( funType->get_parameters().size() == 2 ) {
    186                                                         if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
    187                                                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
    188                                                                         name = typeInst->get_name();
    189                                                                         return true;
     619                        return 0;
     620                }
     621
     622                /// Returns T if the given declaration is a function with parameters (T*, T) for some TypeInstType T, NULL otherwise
     623                TypeInstType *isTypeInstPtrValFn( DeclarationWithType *decl ) {
     624                        if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     625                                if ( funType->get_parameters().size() == 2 ) {
     626                                        if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
     627                                                if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
     628                                                        if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
     629                                                                if ( refType->get_name() == refType2->get_name() ) {
     630                                                                        return refType;
    190631                                                                } // if
    191632                                                        } // if
     
    194635                                } // if
    195636                        } // if
    196                         return false;
    197                 }
    198 
    199                 void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
    200                         assignOps.clear();
     637                        return 0;
     638                }
     639
     640                /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     641                TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
     642                        return decl->get_name() == "?=?" ? isTypeInstPtrValFn( decl ) : 0;
     643                }
     644
     645                /// Returns T if the given declaration is (*?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     646                TypeInstType *isTypeInstCtor( DeclarationWithType *decl ) {
     647                        return decl->get_name() == "?{}" ? isTypeInstPtrFn( decl ) : 0;
     648                }
     649
     650                /// Returns T if the given declaration is (*?{})(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     651                TypeInstType *isTypeInstCopy( DeclarationWithType *decl ) {
     652                        return decl->get_name() == "?{}" ? isTypeInstPtrValFn( decl ) : 0;
     653                }
     654
     655                /// Returns T if the given declaration is (*^?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     656                TypeInstType *isTypeInstDtor( DeclarationWithType *decl ) {
     657                        return decl->get_name() == "^?{}" ? isTypeInstPtrFn( decl ) : 0;
     658                }
     659
     660                /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
     661                /// NULL otherwise
     662                Type *isNoCvPtrFn( DeclarationWithType *decl ) {
     663                        if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     664                                if ( funType->get_parameters().size() == 1 ) {
     665                                        Type::Qualifiers defaultQualifiers;
     666                                        Type *paramType = funType->get_parameters().front()->get_type();
     667                                        if ( paramType->get_qualifiers() != defaultQualifiers ) return 0;
     668
     669                                        if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType ) ) {
     670                                                Type *baseType = pointerType->get_base();
     671                                                if ( baseType->get_qualifiers() == defaultQualifiers ) {
     672                                                        return baseType;
     673                                                } // if
     674                                        } // if
     675                                } // if
     676                        } // if
     677                        return 0;
     678                }
     679
     680                /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
     681                /// NULL otherwise
     682                Type *isNoCvPtrValFn( DeclarationWithType *decl ) {
     683                        if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     684                                if ( funType->get_parameters().size() == 2 ) {
     685                                        Type::Qualifiers defaultQualifiers;
     686                                        Type *paramType1 = funType->get_parameters().front()->get_type();
     687                                        if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
     688                                        Type *paramType2 = funType->get_parameters().back()->get_type();
     689                                        if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
     690
     691                                        if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
     692                                                Type *baseType1 = pointerType->get_base();
     693                                                if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
     694                                                SymTab::Indexer dummy;
     695                                                if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
     696                                                        return baseType1;
     697                                                } // if
     698                                        } // if
     699                                } // if
     700                        } // if
     701                        return 0;
     702                }
     703
     704                /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
     705                /// Only picks assignments where neither parameter is cv-qualified
     706                Type *isAssignment( DeclarationWithType *decl ) {
     707                        return decl->get_name() == "?=?" ? isNoCvPtrValFn( decl ) : 0;
     708                }
     709
     710                /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
     711                /// Only picks ctors where the parameter is not cv-qualified
     712                Type *isCtor( DeclarationWithType *decl ) {
     713                        return decl->get_name() == "?{}" ? isNoCvPtrFn( decl ) : 0;
     714                }
     715
     716                /// returns T if the given declaration is: (*?{})(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
     717                /// Only picks copy constructors where neither parameter is cv-qualified
     718                Type *isCopy( DeclarationWithType *decl ) {
     719                        return decl->get_name() == "?{}" ? isNoCvPtrValFn( decl ) : 0;
     720                }
     721
     722                /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
     723                /// Only picks ctors where the parameter is not cv-qualified
     724                Type *isDtor( DeclarationWithType *decl ) {
     725                        return decl->get_name() == "^?{}" ? isNoCvPtrFn( decl ) : 0;
     726                }
     727
     728                void Pass1::findTypeOps( const std::list< TypeDecl *> &forall ) {
     729                        // what if a nested function uses an assignment operator?
     730                        // assignOps.clear();
    201731                        for ( std::list< TypeDecl *>::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
    202732                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    203733                                        std::string typeName;
    204                                         if ( checkAssignment( *assert, typeName ) ) {
    205                                                 assignOps[ typeName ] = *assert;
     734                                        if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
     735                                                assignOps[ typeInst->get_name() ] = *assert;
     736                                        } else if ( TypeInstType *typeInst = isTypeInstCtor( *assert ) ) {
     737                                                ctorOps[ typeInst->get_name() ] = *assert;
     738                                        } else if ( TypeInstType *typeInst = isTypeInstCopy( *assert ) ) {
     739                                                copyOps[ typeInst->get_name() ] = *assert;
     740                                        } else if ( TypeInstType *typeInst = isTypeInstDtor( *assert ) ) {
     741                                                dtorOps[ typeInst->get_name() ] = *assert;
    206742                                        } // if
    207743                                } // for
     
    210746
    211747                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    212                         if ( functionDecl->get_statements() ) {
    213                                 TyVarMap oldtyVars = scopeTyVars;
     748                        // if this is a assignment function, put it in the map for this scope
     749                        if ( Type *paramType = isAssignment( functionDecl ) ) {
     750                                if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
     751                                        scopedAssignOps.insert( paramType, functionDecl );
     752                                }
     753                        } else if ( Type *paramType = isCtor( functionDecl ) ) {
     754                                if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
     755                                        scopedCtorOps.insert( paramType, functionDecl );
     756                                }
     757                        } else if ( Type *paramType = isCopy( functionDecl ) ) {
     758                                if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
     759                                        scopedCopyOps.insert( paramType, functionDecl );
     760                                }
     761                        } else if ( Type *paramType = isDtor( functionDecl ) ) {
     762                                if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
     763                                        scopedDtorOps.insert( paramType, functionDecl );
     764                                }
     765                        }
     766
     767                        if ( functionDecl->get_statements() ) {         // empty routine body ?
     768                                doBeginScope();
     769                                scopeTyVars.beginScope();
     770                                assignOps.beginScope();
     771                                ctorOps.beginScope();
     772                                copyOps.beginScope();
     773                                dtorOps.beginScope();
     774
    214775                                DeclarationWithType *oldRetval = retval;
    215776                                bool oldUseRetval = useRetval;
    216        
     777
     778                                // process polymorphic return value
    217779                                retval = 0;
    218                                 std::string typeName;
    219                                 if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
     780                                if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
    220781                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    221  
     782
    222783                                        // give names to unnamed return values
    223784                                        if ( retval->get_name() == "" ) {
     
    226787                                        } // if
    227788                                } // if
    228        
    229                                 scopeTyVars.clear();
    230 ///     std::cerr << "clear\n";
     789
     790                                FunctionType *functionType = functionDecl->get_functionType();
    231791                                makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
    232                                 findAssignOps( functionDecl->get_functionType()->get_forall() );
     792                                findTypeOps( functionDecl->get_functionType()->get_forall() );
     793
     794                                std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
     795                                std::list< FunctionType *> functions;
     796                                for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
     797                                        for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
     798                                                findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
     799                                        } // for
     800                                } // for
     801                                for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
     802                                        findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
     803                                } // for
     804
     805                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
     806                                        std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     807                                        if ( adapters.find( mangleName ) == adapters.end() ) {
     808                                                std::string adapterName = makeAdapterName( mangleName );
     809                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ) );
     810                                        } // if
     811                                } // for
     812
    233813                                functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
    234  
    235                                 scopeTyVars = oldtyVars;
    236 ///     std::cerr << "end FunctionDecl: ";
    237 ///     for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    238 ///       std::cerr << i->first << " ";
    239 ///     }
    240 ///     std::cerr << "\n";
     814
     815                                scopeTyVars.endScope();
     816                                assignOps.endScope();
     817                                ctorOps.endScope();
     818                                copyOps.endScope();
     819                                dtorOps.endScope();
    241820                                retval = oldRetval;
    242821                                useRetval = oldUseRetval;
    243                                 // doEndScope();
     822                                doEndScope();
    244823                        } // if
    245824                        return functionDecl;
     
    247826
    248827                TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
    249 ///     std::cerr << "add " << typeDecl->get_name() << "\n";
    250828                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    251829                        return Mutator::mutate( typeDecl );
     
    272850                }
    273851
    274                 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     852                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     853                        Type *polyType = isPolyType( parmType, exprTyVars );
     854                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     855                                std::string typeName = mangleType( polyType );
     856                                if ( seenTypes.count( typeName ) ) return;
     857
     858                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
     859                                arg++;
     860                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
     861                                arg++;
     862                                if ( dynamic_cast< StructInstType* >( polyType ) ) {
     863                                        if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
     864                                                // zero-length arrays are forbidden by C, so don't pass offset for empty struct
     865                                                if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
     866                                                        arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
     867                                                        arg++;
     868                                                }
     869                                        } else {
     870                                                throw SemanticError( "Cannot pass non-struct type for generic struct" );
     871                                        }
     872                                }
     873
     874                                seenTypes.insert( typeName );
     875                        }
     876                }
     877
     878                void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     879                        // pass size/align for type variables
    275880                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
    276881                                ResolvExpr::EqvClass eqvClass;
     
    281886                                                arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
    282887                                                arg++;
     888                                                arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
     889                                                arg++;
    283890                                        } else {
    284                                                 throw SemanticError( "unbound type variable in application ", appExpr );
     891                                                /// xxx - should this be an assertion?
     892                                                throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr );
    285893                                        } // if
    286894                                } // if
    287895                        } // for
     896
     897                        // add size/align for generic types to parameter list
     898                        if ( appExpr->get_function()->get_results().empty() ) return;
     899                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
     900                        assert( funcType );
     901
     902                        std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
     903                        std::list< Expression* >::const_iterator fnArg = arg;
     904                        std::set< std::string > seenTypes; //< names for generic types we've seen
     905
     906                        // a polymorphic return type may need to be added to the argument list
     907                        if ( polyRetType ) {
     908                                Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
     909                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
     910                        }
     911
     912                        // add type information args for presently unseen types in parameter list
     913                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
     914                                VariableExpr *fnArgBase = getBaseVar( *fnArg );
     915                                if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
     916                                passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
     917                        }
    288918                }
    289919
     
    294924                }
    295925
    296                 TypeInstType *isPolyType( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) {
    297                         if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
    298                                 if ( env ) {
    299                                         if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
    300                                                 return isPolyType( newType, env, tyVars );
    301                                         } // if
     926                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
     927                        // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
     928                        // if ( useRetval ) {
     929                        //      assert( retval );
     930                        //      arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) );
     931                        //      arg++;
     932                        // } else {
     933
     934                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
     935                        // using a comma expression.  Possibly change comma expression into statement expression "{}" for multiple
     936                        // return values.
     937                        ObjectDecl *newObj = makeTemporary( retType->clone() );
     938                        Expression *paramExpr = new VariableExpr( newObj );
     939
     940                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
     941                        // otherwise the temporary is already boxed and can be used directly.
     942                        if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
     943                                paramExpr = new AddressExpr( paramExpr );
     944                        } // if
     945                        arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
     946                        arg++;
     947                        // Build a comma expression to call the function and emulate a normal return.
     948                        CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) );
     949                        commaExpr->set_env( appExpr->get_env() );
     950                        appExpr->set_env( 0 );
     951                        return commaExpr;
     952                        // } // if
     953                        // return appExpr;
     954                }
     955
     956                void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
     957                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
     958                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     959                                assert(paramType && "Aggregate parameters should be type expressions");
     960                                paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
     961                        }
     962                }
     963
     964                Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
     965                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
     966                                Type *concrete = env->lookup( typeInst->get_name() );
     967                                if ( concrete == 0 ) {
     968                                        throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
    302969                                } // if
    303                                 if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
    304                                         return typeInst;
    305                                 } else {
    306                                         return 0;
    307                                 } // if
    308                         } else {
    309                                 return 0;
    310                         } // if
    311                 }
    312 
    313                 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
    314                         if ( useRetval ) {
    315                                 assert( retval );
    316                                 arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) );
    317                                 arg++;
    318                         } else {
    319                                 ObjectDecl *newObj = makeTemporary( retType->clone() );
    320                                 Expression *paramExpr = new VariableExpr( newObj );
    321                                 if ( ! isPolyType( newObj->get_type(), env, scopeTyVars ) ) {
    322                                         paramExpr = new AddressExpr( paramExpr );
    323                                 } // if
    324                                 arg = appExpr->get_args().insert( arg, paramExpr );
    325                                 arg++;
    326 ///     stmtsToAdd.push_back( new ExprStmt( noLabels, appExpr ) );
    327                                 CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) );
    328                                 commaExpr->set_env( appExpr->get_env() );
    329                                 appExpr->set_env( 0 );
    330                                 return commaExpr;
    331                         } // if
    332                         return appExpr;
    333                 }
    334 
    335                 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) {
    336                         ResolvExpr::EqvClass eqvClass;
     970                                return concrete;
     971                        } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
     972                                if ( doClone ) {
     973                                        structType = structType->clone();
     974                                }
     975                                replaceParametersWithConcrete( appExpr, structType->get_parameters() );
     976                                return structType;
     977                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
     978                                if ( doClone ) {
     979                                        unionType = unionType->clone();
     980                                }
     981                                replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
     982                                return unionType;
     983                        }
     984                        return type;
     985                }
     986
     987                Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) {
    337988                        assert( env );
    338                         Type *concrete = env->lookup( typeName );
    339                         if ( concrete == 0 ) {
    340                                 throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr );
    341                         } // if
     989                        Type *concrete = replaceWithConcrete( appExpr, polyType );
     990                        // add out-parameter for return value
    342991                        return addRetParam( appExpr, function, concrete, arg );
    343992                }
     
    345994                Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
    346995                        Expression *ret = appExpr;
    347                         if ( ! function->get_returnVals().empty() && isPolyVal( function->get_returnVals().front()->get_type(), tyVars ) ) {
     996                        if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
    348997                                ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg );
    349998                        } // if
    350                         std::string mangleName = SymTab::Mangler::mangle( function );
     999                        std::string mangleName = mangleAdapterName( function, tyVars );
    3511000                        std::string adapterName = makeAdapterName( mangleName );
    3521001
    353                         appExpr->get_args().push_front( appExpr->get_function() );
     1002                        // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
     1003                        Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
     1004                        appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
    3541005                        appExpr->set_function( new NameExpr( adapterName ) );
    355  
     1006
    3561007                        return ret;
    3571008                }
     
    3591010                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    3601011                        assert( ! arg->get_results().empty() );
    361 ///   if ( ! dynamic_cast< PointerType *>( arg->get_results().front() ) ) {
    362                         TypeInstType *typeInst = dynamic_cast< TypeInstType *>( param );
    363                         if ( typeInst && exprTyVars.find( typeInst->get_name() ) != exprTyVars.end() ) {
    364                                 if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {
    365                                         // if the argument's type is a type parameter, we don't need to box again!
     1012                        if ( isPolyType( param, exprTyVars ) ) {
     1013                                if ( isPolyType( arg->get_results().front() ) ) {
     1014                                        // if the argument's type is polymorphic, we don't need to box again!
    3661015                                        return;
    3671016                                } else if ( arg->get_results().front()->get_isLvalue() ) {
    368                                         // VariableExpr and MemberExpr are lvalues
    369                                         arg = new AddressExpr( arg );
     1017                                        // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
     1018                                        // xxx - need to test that this code is still reachable
     1019                                        if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
     1020                                                commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
     1021                                        } else {
     1022                                                arg = new AddressExpr( arg );
     1023                                        }
    3701024                                } else {
    371                                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 );
     1025                                        // use type computed in unification to declare boxed variables
     1026                                        Type * newType = param->clone();
     1027                                        if ( env ) env->apply( newType );
     1028                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, newType, 0 );
    3721029                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    3731030                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     
    3791036                                } // if
    3801037                        } // if
    381 ///   }
    382                 }
    383 
     1038                }
     1039
     1040                /// cast parameters to polymorphic functions so that types are replaced with
     1041                /// void * if they are type parameters in the formal type.
     1042                /// this gets rid of warnings from gcc.
    3841043                void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
    385                         Type *newType = formal->clone();
    386                         std::list< FunctionType *> functions;
    387                         // instead of functions needing adapters, this really ought to look for
    388                         // any function mentioning a polymorphic type
    389                         findAndReplaceFunction( newType, functions, tyVars, needsAdapter );
    390                         if ( ! functions.empty() ) {
     1044                        Type * newType = formal->clone();
     1045                        if ( getFunctionType( newType ) ) {
     1046                                newType = ScrubTyVars::scrub( newType, tyVars );
    3911047                                actual = new CastExpr( actual, newType );
    392                         } else {
    393                                 delete newType;
    3941048                        } // if
    3951049                }
    3961050
    3971051                void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    398 ///   std::cout << "function is ";
    399 ///   function->print( std::cout );
    4001052                        for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
    401 ///     std::cout << "parameter is ";
    402 ///     (*param)->print( std::fcout );
    403 ///     std::cout << std::endl << "argument is ";
    404 ///     (*arg)->print( std::cout );
    4051053                                assert( arg != appExpr->get_args().end() );
    4061054                                addCast( *arg, (*param)->get_type(), exprTyVars );
     
    4141062                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
    4151063                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
    416                                         assert( inferParam != appExpr->get_inferParams().end() );
     1064                                        assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
    4171065                                        Expression *newExpr = inferParam->second.expr->clone();
    4181066                                        addCast( newExpr, (*assert)->get_type(), tyVars );
     
    4371085                        // actually make the adapter type
    4381086                        FunctionType *adapter = adaptee->clone();
    439                         if ( ! adapter->get_returnVals().empty() && isPolyVal( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
     1087                        if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
    4401088                                makeRetParm( adapter );
    4411089                        } // if
     
    4471095                        assert( param );
    4481096                        assert( arg );
    449 ///   std::cout << "arg type is ";
    450 ///   arg->get_type()->print( std::cout );
    451 ///   std::cout << "param type is ";
    452 ///   param->get_type()->print( std::cout );
    453 ///   std::cout << " tyVars are: ";
    454 ///   printTyVarMap( std::cout, tyVars );
    455                         if ( isPolyVal( realParam->get_type(), tyVars ) ) {
    456 ///     if ( dynamic_cast< PointerType *>( arg->get_type() ) ) {
    457 ///       return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() );
    458 ///     } else {
    459                                 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    460                                 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
    461                                 deref->get_results().push_back( arg->get_type()->clone() );
    462                                 return deref;
    463 ///     }
     1097                        if ( isPolyType( realParam->get_type(), tyVars ) ) {
     1098                                if ( ! isPolyType( arg->get_type() ) ) {
     1099                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     1100                                        deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
     1101                                        deref->get_results().push_back( arg->get_type()->clone() );
     1102                                        return deref;
     1103                                } // if
    4641104                        } // if
    4651105                        return new VariableExpr( param );
     
    4771117                }
    4781118
    479 
    480 
    4811119                FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
    4821120                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
     
    4861124                        ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
    4871125                        Statement *bodyStmt;
    488  
     1126
    4891127                        std::list< TypeDecl *>::iterator tyArg = realType->get_forall().begin();
    4901128                        std::list< TypeDecl *>::iterator tyParam = adapterType->get_forall().begin();
     
    5001138                                } // for
    5011139                        } // for
    502  
     1140
    5031141                        std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
    5041142                        std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
    5051143                        std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
    506                         param++;                // skip adaptee parameter
     1144                        param++;                // skip adaptee parameter in the adapter type
    5071145                        if ( realType->get_returnVals().empty() ) {
     1146                                // void return
    5081147                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
    5091148                                bodyStmt = new ExprStmt( noLabels, adapteeApp );
    510                         } else if ( isPolyVal( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
     1149                        } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
     1150                                // return type T
    5111151                                if ( (*param)->get_name() == "" ) {
    5121152                                        (*param)->set_name( "_ret" );
     
    5441184                        } // for
    5451185
    546                         // parameter function types for which an appropriate adapter has been generated.
    547                         // we cannot use the types after applying substitutions, since two different
    548                         // parameter types may be unified to the same type
     1186                        // parameter function types for which an appropriate adapter has been generated.  we cannot use the types
     1187                        // after applying substitutions, since two different parameter types may be unified to the same type
    5491188                        std::set< std::string > adaptersDone;
    5501189
     
    5541193                                std::string mangleName = SymTab::Mangler::mangle( realFunction );
    5551194
    556                                 // only attempt to create an adapter or pass one as a parameter if we haven't
    557                                 // already done so for this pre-substitution parameter function type.
     1195                                // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
     1196                                // pre-substitution parameter function type.
    5581197                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    559                                         std::string mangleName = SymTab::Mangler::mangle( realFunction );
    5601198                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
    561                                        
    562                                         // apply substitution to type variables to figure out what the
    563                                         // adapter's type should look like
     1199
     1200                                        // apply substitution to type variables to figure out what the adapter's type should look like
    5641201                                        assert( env );
    5651202                                        env->apply( realFunction );
    5661203                                        mangleName = SymTab::Mangler::mangle( realFunction );
    567 
    568                                         if ( needsAdapter( realFunction, exprTyVars, true ) ) {
    569                                                 // the function still contains type variables, which means we are in a polymorphic
    570                                                 // context and the adapter function is a parameter - call the parameter and don't
    571                                                 // create a new adapter.
    572                                                 appExpr->get_args().push_front( new NameExpr( makeAdapterName ( mangleName ) ) );
    573                                         } else {
    574                                                 if ( isPolyRet( originalFunction, exprTyVars ) ) {
    575                                                         // if the return type involved polymorphic types, then
    576                                                         // the adapter will need to take those polymorphic types
    577                                                         // as pointers. Therefore, there can be two different
    578                                                         // functions with the same mangled name, so we need two adapter map
    579                                                         // stacks and also we need the mangled names to be different.
    580                                                         mangleName += "polyret_";
    581                                                 }
    582 
    583                                                 AdapterMap & adapters = Pass1::adapters.top();
    584                                                 AdapterMap::iterator adapter = adapters.find( mangleName );
    585                                                 if ( adapter == adapters.end() ) {
    586                                                         // adapter has not been created yet in the current scope, so define it
    587                                                         FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
    588                                                         adapter = adapters.insert( adapters.begin(), std::pair< std::string, FunctionDecl *>( mangleName, newAdapter ) );
    589                                                         stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
    590                                                 } // if
    591                                                 assert( adapter != adapters.end() );
    592 
    593                                                 // add the appropriate adapter as a parameter
    594                                                 appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
     1204                                        mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
     1205
     1206                                        typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     1207                                        AdapterIter adapter = adapters.find( mangleName );
     1208                                        if ( adapter == adapters.end() ) {
     1209                                                // adapter has not been created yet in the current scope, so define it
     1210                                                FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
     1211                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     1212                                                adapter = answer.first;
     1213                                                stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
    5951214                                        } // if
     1215                                        assert( adapter != adapters.end() );
     1216
     1217                                        // add the appropriate adapter as a parameter
     1218                                        appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
    5961219                                } // if
    5971220                        } // for
    598                 }
    599 
    600                 TypeInstType *isPolyPtr( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) {
    601                         if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    602                                 return isPolyType( ptr->get_base(), env, tyVars );
    603                         } else if ( env ) {
    604                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
    605                                         if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
    606                                                 return isPolyPtr( newType, env, tyVars );
    607                                         } // if
    608                                 } // if
    609                         } // if
    610                         return 0;
    611                 }
    612 
    613                 TypeInstType *isPolyPtrPtr( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) {
    614                         if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    615                                 return isPolyPtr( ptr->get_base(), env, tyVars );
    616                         } else if ( env ) {
    617                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
    618                                         if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
    619                                                 return isPolyPtrPtr( newType, env, tyVars );
    620                                         } // if
    621                                 } // if
    622                         } // if
    623                         return 0;
    624                 }
    625 
    626                 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, std::string polyName, bool isIncr ) {
     1221                } // passAdapters
     1222
     1223                Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
    6271224                        NameExpr *opExpr;
    6281225                        if ( isIncr ) {
     
    6371234                                addAssign->get_args().push_back( appExpr->get_args().front() );
    6381235                        } // if
    639                         addAssign->get_args().push_back( new NameExpr( polyName ) );
     1236                        addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
    6401237                        addAssign->get_results().front() = appExpr->get_results().front()->clone();
    6411238                        if ( appExpr->get_env() ) {
     
    6541251                                                assert( ! appExpr->get_results().empty() );
    6551252                                                assert( appExpr->get_args().size() == 2 );
    656                                                 TypeInstType *typeInst1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), env, scopeTyVars );
    657                                                 TypeInstType *typeInst2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), env, scopeTyVars );
    658                                                 assert( ! typeInst1 || ! typeInst2 );
     1253                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
     1254                                                Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
     1255                                                assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
    6591256                                                UntypedExpr *ret = 0;
    660                                                 if ( typeInst1 || typeInst2 ) {
     1257                                                if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
    6611258                                                        ret = new UntypedExpr( new NameExpr( "?+?" ) );
    6621259                                                } // if
    663                                                 if ( typeInst1 ) {
     1260                                                if ( baseType1 ) {
    6641261                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    6651262                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    666                                                         multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
     1263                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    6671264                                                        ret->get_args().push_back( appExpr->get_args().front() );
    6681265                                                        ret->get_args().push_back( multiply );
    669                                                 } else if ( typeInst2 ) {
     1266                                                } else if ( baseType2 ) {
    6701267                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    6711268                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    672                                                         multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );
     1269                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    6731270                                                        ret->get_args().push_back( multiply );
    6741271                                                        ret->get_args().push_back( appExpr->get_args().back() );
    6751272                                                } // if
    676                                                 if ( typeInst1 || typeInst2 ) {
     1273                                                if ( baseType1 || baseType2 ) {
    6771274                                                        ret->get_results().push_front( appExpr->get_results().front()->clone() );
    6781275                                                        if ( appExpr->get_env() ) {
     
    6871284                                                assert( ! appExpr->get_results().empty() );
    6881285                                                assert( ! appExpr->get_args().empty() );
    689                                                 if ( isPolyType( appExpr->get_results().front(), env, scopeTyVars ) ) {
     1286                                                if ( isPolyType( appExpr->get_results().front(), scopeTyVars, env ) ) {
    6901287                                                        Expression *ret = appExpr->get_args().front();
    6911288                                                        delete ret->get_results().front();
     
    7021299                                                assert( ! appExpr->get_results().empty() );
    7031300                                                assert( appExpr->get_args().size() == 1 );
    704                                                 if ( TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars ) ) {
     1301                                                if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
    7051302                                                        Type *tempType = appExpr->get_results().front()->clone();
    7061303                                                        if ( env ) {
     
    7161313                                                                assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
    7171314                                                        } // if
    718                                                         CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "?++" ) );
     1315                                                        CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
    7191316                                                        return new CommaExpr( firstComma, tempExpr );
    7201317                                                } // if
     
    7221319                                                assert( ! appExpr->get_results().empty() );
    7231320                                                assert( appExpr->get_args().size() == 1 );
    724                                                 if ( TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars ) ) {
    725                                                         return makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "++?" );
     1321                                                if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
     1322                                                        return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
    7261323                                                } // if
    7271324                                        } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
    7281325                                                assert( ! appExpr->get_results().empty() );
    7291326                                                assert( appExpr->get_args().size() == 2 );
    730                                                 TypeInstType *typeInst1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), env, scopeTyVars );
    731                                                 TypeInstType *typeInst2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), env, scopeTyVars );
    732                                                 if ( typeInst1 && typeInst2 ) {
     1327                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
     1328                                                Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
     1329                                                if ( baseType1 && baseType2 ) {
    7331330                                                        UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
    7341331                                                        divide->get_args().push_back( appExpr );
    735                                                         divide->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
     1332                                                        divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    7361333                                                        divide->get_results().push_front( appExpr->get_results().front()->clone() );
    7371334                                                        if ( appExpr->get_env() ) {
     
    7401337                                                        } // if
    7411338                                                        return divide;
    742                                                 } else if ( typeInst1 ) {
     1339                                                } else if ( baseType1 ) {
    7431340                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    7441341                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    745                                                         multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
     1342                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    7461343                                                        appExpr->get_args().back() = multiply;
    747                                                 } else if ( typeInst2 ) {
     1344                                                } else if ( baseType2 ) {
    7481345                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    7491346                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    750                                                         multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );
     1347                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    7511348                                                        appExpr->get_args().front() = multiply;
    7521349                                                } // if
     
    7541351                                                assert( ! appExpr->get_results().empty() );
    7551352                                                assert( appExpr->get_args().size() == 2 );
    756                                                 TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars );
    757                                                 if ( typeInst ) {
     1353                                                Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env );
     1354                                                if ( baseType ) {
    7581355                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    7591356                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    760                                                         multiply->get_args().push_back( new NameExpr( typeInst->get_name() ) );
     1357                                                        multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
    7611358                                                        appExpr->get_args().back() = multiply;
    7621359                                                } // if
     
    7691366
    7701367                Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
    771 ///    std::cerr << "mutate appExpr: ";
    772 ///    for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    773 ///       std::cerr << i->first << " ";
    774 ///    }
    775 ///    std::cerr << "\n";
     1368                        // std::cerr << "mutate appExpr: ";
     1369                        // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
     1370                        //      std::cerr << i->first << " ";
     1371                        // }
     1372                        // std::cerr << "\n";
    7761373                        bool oldUseRetval = useRetval;
    7771374                        useRetval = false;
     
    7791376                        mutateAll( appExpr->get_args(), *this );
    7801377                        useRetval = oldUseRetval;
    781  
     1378
    7821379                        assert( ! appExpr->get_function()->get_results().empty() );
    7831380                        PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
     
    7851382                        FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
    7861383                        assert( function );
    787  
     1384
    7881385                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
    7891386                                return newExpr;
    7901387                        } // if
    791  
     1388
    7921389                        Expression *ret = appExpr;
    793  
     1390
    7941391                        std::list< Expression *>::iterator arg = appExpr->get_args().begin();
    7951392                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    796  
    797                         std::string typeName;
    798                         if ( isPolyRet( function, typeName ) ) {
    799                                 ret = addPolyRetParam( appExpr, function, typeName, arg );
     1393
     1394                        TyVarMap exprTyVars( (TypeDecl::Kind)-1 );
     1395                        makeTyVarMap( function, exprTyVars );
     1396                        ReferenceToType *polyRetType = isPolyRet( function );
     1397
     1398                        if ( polyRetType ) {
     1399                                ret = addPolyRetParam( appExpr, function, polyRetType, arg );
    8001400                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    801 ///     std::cerr << "needs adapter: ";
    802 ///     for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    803 ///       std::cerr << i->first << " ";
    804 ///     }
    805 ///     std::cerr << "\n";
     1401                                // std::cerr << "needs adapter: ";
     1402                                // printTyVarMap( std::cerr, scopeTyVars );
     1403                                // std::cerr << *env << std::endl;
    8061404                                // change the application so it calls the adapter rather than the passed function
    8071405                                ret = applyAdapter( appExpr, function, arg, scopeTyVars );
    8081406                        } // if
    8091407                        arg = appExpr->get_args().begin();
    810  
    811                         TyVarMap exprTyVars;
    812                         makeTyVarMap( function, exprTyVars );
    813  
    814                         passTypeVars( appExpr, arg, exprTyVars );
     1408
     1409                        passTypeVars( appExpr, polyRetType, arg, exprTyVars );
    8151410                        addInferredParams( appExpr, function, arg, exprTyVars );
    8161411
    8171412                        arg = paramBegin;
    818  
     1413
    8191414                        boxParams( appExpr, function, arg, exprTyVars );
    820 
    8211415                        passAdapters( appExpr, function, exprTyVars );
    8221416
     
    8251419
    8261420                Expression *Pass1::mutate( UntypedExpr *expr ) {
    827                         if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), env, scopeTyVars ) ) {
     1421                        if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
    8281422                                if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
    8291423                                        if ( name->get_name() == "*?" ) {
     
    8401434                Expression *Pass1::mutate( AddressExpr *addrExpr ) {
    8411435                        assert( ! addrExpr->get_arg()->get_results().empty() );
     1436
     1437                        bool needs = false;
     1438                        if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
     1439                                if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
     1440                                        if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
     1441                                                if ( name->get_name() == "*?" ) {
     1442                                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
     1443                                                                assert( ! appExpr->get_function()->get_results().empty() );
     1444                                                                PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
     1445                                                                assert( pointer );
     1446                                                                FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
     1447                                                                assert( function );
     1448                                                                needs = needsAdapter( function, scopeTyVars );
     1449                                                        } // if
     1450                                                } // if
     1451                                        } // if
     1452                                } // if
     1453                        } // if
     1454                        // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
     1455                        // out of the if condition.
     1456                        bool polytype = isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env );
    8421457                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
    843                         if ( isPolyType( addrExpr->get_arg()->get_results().front(), env, scopeTyVars ) ) {
     1458                        if ( polytype || needs ) {
    8441459                                Expression *ret = addrExpr->get_arg();
    8451460                                delete ret->get_results().front();
     
    8531468                }
    8541469
    855                 Statement * Pass1::mutate(ReturnStmt *retStmt) {
    856                         // a cast expr on a polymorphic return value is either redundant or invalid
    857                         while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( retStmt->get_expr() ) ) {
    858                                 retStmt->set_expr( castExpr->get_arg() );
    859                                 retStmt->get_expr()->set_env( castExpr->get_env() );
    860                                 castExpr->set_env( 0 );
    861                                 castExpr->set_arg( 0 );
    862                                 delete castExpr;
    863                         }
    864                         if ( retval && retStmt->get_expr() ) {
    865                                 assert( ! retStmt->get_expr()->get_results().empty() );
    866                                 if ( retStmt->get_expr()->get_results().front()->get_isLvalue() ) {
    867 ///       retStmt->set_expr( mutateExpression( retStmt->get_expr() ) );
    868                                         TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() );
    869                                         assert( typeInst );
    870                                         std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
     1470                /// Wraps a function declaration in a new pointer-to-function variable expression
     1471                VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
     1472                        // line below cloned from FixFunction.cc
     1473                        // xxx - functionObj is never added to a list of declarations...
     1474                        ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
     1475                                                                  new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
     1476                        functionObj->set_mangleName( functionDecl->get_mangleName() );
     1477                        functionObj->set_scopeLevel( functionDecl->get_scopeLevel() );
     1478                        return new VariableExpr( functionObj );
     1479                }
     1480
     1481                /// Finds the operation declaration for a given type in one of the two maps
     1482                DeclarationWithType* findOpForType( Type *formalType, const ScopedMap< std::string, DeclarationWithType* >& ops, ResolvExpr::TypeMap< DeclarationWithType >& scopedOps ) {
     1483                        if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
     1484                                ScopedMap< std::string, DeclarationWithType *>::const_iterator opIt = ops.find( formalTypeInstType->get_name() );
     1485                                return opIt == ops.end() ? 0 : opIt->second;
     1486                        } else {
     1487                                return scopedOps.find( formalType );
     1488                        }
     1489                }
     1490
     1491                /// Adds an assertion parameter to the application expression for the actual assertion declaration valued with the assert op
     1492                void addAssertionFor( ApplicationExpr *appExpr, DeclarationWithType *actualDecl, DeclarationWithType *assertOp ) {
     1493                        appExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
     1494                                        = ParamEntry( assertOp->get_uniqueId(), assertOp->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertOp ) );
     1495                }
     1496
     1497                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
     1498                        if ( retval && returnStmt->get_expr() ) {
     1499                                assert( ! returnStmt->get_expr()->get_results().empty() );
     1500                                // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
     1501                                // if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) {
     1502                                // by this point, a cast expr on a polymorphic return value is redundant
     1503                                while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( returnStmt->get_expr() ) ) {
     1504                                        returnStmt->set_expr( castExpr->get_arg() );
     1505                                        returnStmt->get_expr()->set_env( castExpr->get_env() );
     1506                                        castExpr->set_env( 0 );
     1507                                        castExpr->set_arg( 0 );
     1508                                        delete castExpr;
     1509                                } //while
     1510
     1511                                // find assignment operator for (polymorphic) return type
     1512                                ApplicationExpr *assignExpr = 0;
     1513                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
     1514                                        // find assignment operator for type variable
     1515                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    8711516                                        if ( assignIter == assignOps.end() ) {
    872                                                 throw SemanticError( "Attempt to return dtype or ftype object in ", retStmt->get_expr() );
     1517                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    8731518                                        } // if
    874                                         ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
    875                                         Expression *retParm = new NameExpr( retval->get_name() );
    876                                         retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
    877                                         assignExpr->get_args().push_back( retParm );
    878                                         assignExpr->get_args().push_back( retStmt->get_expr() );
    879                                         stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) );
    880                                 } else {
    881                                         useRetval = true;
    882                                         stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( retStmt->get_expr() ) ) );
    883                                         useRetval = false;
    884                                 } // if
    885                                 retStmt->set_expr( 0 );
     1519                                        assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
     1520                                } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
     1521                                        // find assignment operator for generic type
     1522                                        DeclarationWithType *functionDecl = scopedAssignOps.find( refType );
     1523                                        if ( ! functionDecl ) {
     1524                                                throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
     1525                                        }
     1526
     1527                                        // wrap it up in an application expression
     1528                                        assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
     1529                                        assignExpr->set_env( env->clone() );
     1530
     1531                                        // find each of its needed secondary assignment operators
     1532                                        std::list< Expression* > &tyParams = refType->get_parameters();
     1533                                        std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
     1534                                        std::list< Expression* >::const_iterator tyIt = tyParams.begin();
     1535                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
     1536                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
     1537                                                // Add appropriate mapping to assignment expression environment
     1538                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
     1539                                                assert( formalTypeExpr && "type parameters must be type expressions" );
     1540                                                Type *formalType = formalTypeExpr->get_type();
     1541                                                assignExpr->get_env()->add( (*forallIt)->get_name(), formalType );
     1542
     1543                                                // skip non-otype parameters (ftype/dtype)
     1544                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue;
     1545
     1546                                                // find otype operators for formal type
     1547                                                DeclarationWithType *assertAssign = findOpForType( formalType, assignOps, scopedAssignOps );
     1548                                                if ( ! assertAssign ) throw SemanticError( "No assignment operation found for ", formalType );
     1549
     1550                                                DeclarationWithType *assertCtor = findOpForType( formalType, ctorOps, scopedCtorOps );
     1551                                                if ( ! assertCtor ) throw SemanticError( "No default constructor found for ", formalType );
     1552
     1553                                                DeclarationWithType *assertCopy = findOpForType( formalType, copyOps, scopedCopyOps );
     1554                                                if ( ! assertCopy ) throw SemanticError( "No copy constructor found for ", formalType );
     1555
     1556                                                DeclarationWithType *assertDtor = findOpForType( formalType, dtorOps, scopedDtorOps );
     1557                                                if ( ! assertDtor ) throw SemanticError( "No destructor found for ", formalType );
     1558
     1559                                                // add inferred parameters for otype operators to assignment expression
     1560                                                // NOTE: Code here assumes that first four assertions are assign op, ctor, copy ctor, dtor, in that order
     1561                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
     1562                                                assert( asserts.size() >= 4 && "Type param needs otype operator assertions" );
     1563
     1564                                                std::list< DeclarationWithType* >::iterator actualIt = asserts.begin();
     1565                                                addAssertionFor( assignExpr, *actualIt, assertAssign );
     1566                                                ++actualIt;
     1567                                                addAssertionFor( assignExpr, *actualIt, assertCtor );
     1568                                                ++actualIt;
     1569                                                addAssertionFor( assignExpr, *actualIt, assertCopy );
     1570                                                ++actualIt;
     1571                                                addAssertionFor( assignExpr, *actualIt, assertDtor );
     1572
     1573                                        }
     1574                                }
     1575                                assert( assignExpr );
     1576
     1577                                // replace return statement with appropriate assignment to out parameter
     1578                                Expression *retParm = new NameExpr( retval->get_name() );
     1579                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
     1580                                assignExpr->get_args().push_back( retParm );
     1581                                assignExpr->get_args().push_back( returnStmt->get_expr() );
     1582                                stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) );
     1583                                // } else {
     1584                                //      useRetval = true;
     1585                                //      stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( returnStmt->get_expr() ) ) );
     1586                                //      useRetval = false;
     1587                                // } // if
     1588                                returnStmt->set_expr( 0 );
    8861589                        } else {
    887                                 retStmt->set_expr( mutateExpression( retStmt->get_expr() ) );
     1590                                returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
    8881591                        } // if
    889                         return retStmt;
     1592                        return returnStmt;
    8901593                }
    8911594
    8921595                Type * Pass1::mutate( PointerType *pointerType ) {
    893                         TyVarMap oldtyVars = scopeTyVars;
     1596                        scopeTyVars.beginScope();
    8941597                        makeTyVarMap( pointerType, scopeTyVars );
    895  
     1598
    8961599                        Type *ret = Mutator::mutate( pointerType );
    897  
    898                         scopeTyVars = oldtyVars;
     1600
     1601                        scopeTyVars.endScope();
    8991602                        return ret;
    9001603                }
    9011604
    9021605                Type * Pass1::mutate( FunctionType *functionType ) {
    903                         TyVarMap oldtyVars = scopeTyVars;
     1606                        scopeTyVars.beginScope();
    9041607                        makeTyVarMap( functionType, scopeTyVars );
    905  
     1608
    9061609                        Type *ret = Mutator::mutate( functionType );
    907  
    908                         scopeTyVars = oldtyVars;
     1610
     1611                        scopeTyVars.endScope();
    9091612                        return ret;
    9101613                }
    9111614
    9121615                void Pass1::doBeginScope() {
    913                         // actually, maybe this could (should?) push
    914                         // a copy of the current map
    915                         adapters.push(AdapterMap());
     1616                        adapters.beginScope();
     1617                        scopedAssignOps.beginScope();
     1618                        scopedCtorOps.beginScope();
     1619                        scopedCopyOps.beginScope();
     1620                        scopedDtorOps.beginScope();
    9161621                }
    9171622
    9181623                void Pass1::doEndScope() {
    919                         adapters.pop();
     1624                        adapters.endScope();
     1625                        scopedAssignOps.endScope();
     1626                        scopedCtorOps.endScope();
     1627                        scopedCopyOps.endScope();
     1628                        scopedDtorOps.endScope();
    9201629                }
    9211630
    9221631////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
    923 
    924                 Pass2::Pass2() {}
    9251632
    9261633                void Pass2::addAdapters( FunctionType *functionType ) {
     
    9341641                        std::set< std::string > adaptersDone;
    9351642                        for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    936                                 std::string mangleName = SymTab::Mangler::mangle( *funType );
     1643                                std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
    9371644                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    9381645                                        std::string adapterName = makeAdapterName( mangleName );
     
    9411648                                }
    9421649                        }
    943 ///  deleteAll( functions );
     1650//  deleteAll( functions );
    9441651                }
    9451652
     
    9731680
    9741681                Type * Pass2::mutate( PointerType *pointerType ) {
    975                         TyVarMap oldtyVars = scopeTyVars;
     1682                        scopeTyVars.beginScope();
    9761683                        makeTyVarMap( pointerType, scopeTyVars );
    977  
     1684
    9781685                        Type *ret = Mutator::mutate( pointerType );
    979  
    980                         scopeTyVars = oldtyVars;
     1686
     1687                        scopeTyVars.endScope();
    9811688                        return ret;
    9821689                }
    9831690
    9841691                Type *Pass2::mutate( FunctionType *funcType ) {
    985                         TyVarMap oldtyVars = scopeTyVars;
     1692                        scopeTyVars.beginScope();
    9861693                        makeTyVarMap( funcType, scopeTyVars );
    987  
    988                         std::string typeName;
    989                         if ( isPolyRet( funcType, typeName ) ) {
     1694
     1695                        // move polymorphic return type to parameter list
     1696                        if ( isPolyRet( funcType ) ) {
    9901697                                DeclarationWithType *ret = funcType->get_returnVals().front();
    9911698                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
     
    9931700                                funcType->get_returnVals().pop_front();
    9941701                        }
    995  
     1702
     1703                        // add size/align and assertions for type parameters to parameter list
    9961704                        std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
    9971705                        std::list< DeclarationWithType *> inferredParams;
    998                         ObjectDecl *newObj = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
    999 ///   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
     1706                        ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
     1707                        ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
     1708                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
    10001709                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
    1001                                 ObjectDecl *thisParm;
     1710                                ObjectDecl *sizeParm, *alignParm;
     1711                                // add all size and alignment parameters to parameter list
    10021712                                if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
    1003                                         thisParm = newObj->clone();
    1004                                         thisParm->set_name( (*tyParm)->get_name() );
    1005                                         last = funcType->get_parameters().insert( last, thisParm );
     1713                                        TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
     1714                                        std::string parmName = mangleType( &parmType );
     1715
     1716                                        sizeParm = newObj.clone();
     1717                                        sizeParm->set_name( sizeofName( parmName ) );
     1718                                        last = funcType->get_parameters().insert( last, sizeParm );
     1719                                        ++last;
     1720
     1721                                        alignParm = newObj.clone();
     1722                                        alignParm->set_name( alignofName( parmName ) );
     1723                                        last = funcType->get_parameters().insert( last, alignParm );
    10061724                                        ++last;
    10071725                                }
     1726                                // move all assertions into parameter list
    10081727                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
    1009 ///      *assert = (*assert)->acceptMutator( *this );
     1728//      *assert = (*assert)->acceptMutator( *this );
    10101729                                        inferredParams.push_back( *assert );
    10111730                                }
    10121731                                (*tyParm)->get_assertions().clear();
    10131732                        }
    1014                         delete newObj;
     1733
     1734                        // add size/align for generic parameter types to parameter list
     1735                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
     1736                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
     1737                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1738                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     1739                                        std::string typeName = mangleType( polyType );
     1740                                        if ( seenTypes.count( typeName ) ) continue;
     1741
     1742                                        ObjectDecl *sizeParm, *alignParm, *offsetParm;
     1743                                        sizeParm = newObj.clone();
     1744                                        sizeParm->set_name( sizeofName( typeName ) );
     1745                                        last = funcType->get_parameters().insert( last, sizeParm );
     1746                                        ++last;
     1747
     1748                                        alignParm = newObj.clone();
     1749                                        alignParm->set_name( alignofName( typeName ) );
     1750                                        last = funcType->get_parameters().insert( last, alignParm );
     1751                                        ++last;
     1752
     1753                                        if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
     1754                                                // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
     1755                                                if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
     1756                                                        offsetParm = newPtr.clone();
     1757                                                        offsetParm->set_name( offsetofName( typeName ) );
     1758                                                        last = funcType->get_parameters().insert( last, offsetParm );
     1759                                                        ++last;
     1760                                                }
     1761                                        }
     1762
     1763                                        seenTypes.insert( typeName );
     1764                                }
     1765                        }
     1766
     1767                        // splice assertion parameters into parameter list
    10151768                        funcType->get_parameters().splice( last, inferredParams );
    10161769                        addAdapters( funcType );
    10171770                        mutateAll( funcType->get_returnVals(), *this );
    10181771                        mutateAll( funcType->get_parameters(), *this );
    1019  
    1020                         scopeTyVars = oldtyVars;
     1772
     1773                        scopeTyVars.endScope();
    10211774                        return funcType;
     1775                }
     1776
     1777//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
     1778
     1779                /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
     1780                bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
     1781                        bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
     1782
     1783                        // substitute concrete types for given parameters, and incomplete types for placeholders
     1784                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     1785                        std::list< Expression* >::const_iterator param = params.begin();
     1786                        for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
     1787        //                      switch ( (*baseParam)->get_kind() ) {
     1788        //                      case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
     1789                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     1790                                        assert(paramType && "Aggregate parameters should be type expressions");
     1791                                        out.push_back( paramType->clone() );
     1792                                        // check that the substituted type isn't a type variable itself
     1793                                        if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
     1794                                                allConcrete = false;
     1795                                        }
     1796        //                              break;
     1797        //                      }
     1798        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1799        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1800        //                              break;
     1801        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1802        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1803        //                              break;
     1804        //                      }
     1805                        }
     1806
     1807                        // if any parameters left over, not done
     1808                        if ( baseParam != baseParams.end() ) return false;
     1809        //              // if not enough parameters given, substitute remaining incomplete types for placeholders
     1810        //              for ( ; baseParam != baseParams.end(); ++baseParam ) {
     1811        //                      switch ( (*baseParam)->get_kind() ) {
     1812        //                      case TypeDecl::Any:    // no more substitutions here, fail early
     1813        //                              return false;
     1814        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1815        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1816        //                              break;
     1817        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1818        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1819        //                              break;
     1820        //                      }
     1821        //              }
     1822
     1823                        return allConcrete;
     1824                }
     1825
     1826                /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
     1827                void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
     1828                                                                std::list< Declaration* >& out ) {
     1829                        // substitute types into new members
     1830                        TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     1831                        for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
     1832                                Declaration *newMember = (*member)->clone();
     1833                                subs.apply(newMember);
     1834                                out.push_back( newMember );
     1835                        }
     1836                }
     1837
     1838                Type* GenericInstantiator::mutate( StructInstType *inst ) {
     1839                        // mutate subtypes
     1840                        Type *mutated = Mutator::mutate( inst );
     1841                        inst = dynamic_cast< StructInstType* >( mutated );
     1842                        if ( ! inst ) return mutated;
     1843
     1844                        // exit early if no need for further mutation
     1845                        if ( inst->get_parameters().empty() ) return inst;
     1846                        assert( inst->get_baseParameters() && "Base struct has parameters" );
     1847
     1848                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1849                        std::list< TypeExpr* > typeSubs;
     1850                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1851                                deleteAll( typeSubs );
     1852                                return inst;
     1853                        }
     1854
     1855                        // make concrete instantiation of generic type
     1856                        StructDecl *concDecl = lookup( inst, typeSubs );
     1857                        if ( ! concDecl ) {
     1858                                // set concDecl to new type, insert type declaration into statements to add
     1859                                concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
     1860                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
     1861                                DeclMutator::addDeclaration( concDecl );
     1862                                insert( inst, typeSubs, concDecl );
     1863                        }
     1864                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
     1865                        newInst->set_baseStruct( concDecl );
     1866
     1867                        deleteAll( typeSubs );
     1868                        delete inst;
     1869                        return newInst;
     1870                }
     1871
     1872                Type* GenericInstantiator::mutate( UnionInstType *inst ) {
     1873                        // mutate subtypes
     1874                        Type *mutated = Mutator::mutate( inst );
     1875                        inst = dynamic_cast< UnionInstType* >( mutated );
     1876                        if ( ! inst ) return mutated;
     1877
     1878                        // exit early if no need for further mutation
     1879                        if ( inst->get_parameters().empty() ) return inst;
     1880                        assert( inst->get_baseParameters() && "Base union has parameters" );
     1881
     1882                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1883                        std::list< TypeExpr* > typeSubs;
     1884                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1885                                deleteAll( typeSubs );
     1886                                return inst;
     1887                        }
     1888
     1889                        // make concrete instantiation of generic type
     1890                        UnionDecl *concDecl = lookup( inst, typeSubs );
     1891                        if ( ! concDecl ) {
     1892                                // set concDecl to new type, insert type declaration into statements to add
     1893                                concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
     1894                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
     1895                                DeclMutator::addDeclaration( concDecl );
     1896                                insert( inst, typeSubs, concDecl );
     1897                        }
     1898                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
     1899                        newInst->set_baseUnion( concDecl );
     1900
     1901                        deleteAll( typeSubs );
     1902                        delete inst;
     1903                        return newInst;
     1904                }
     1905
     1906        //      /// Gets the base struct or union declaration for a member expression; NULL if not applicable
     1907        //      AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
     1908        //              // get variable for member aggregate
     1909        //              VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
     1910        //              if ( ! varExpr ) return NULL;
     1911        //
     1912        //              // get object for variable
     1913        //              ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
     1914        //              if ( ! objectDecl ) return NULL;
     1915        //
     1916        //              // get base declaration from object type
     1917        //              Type *objectType = objectDecl->get_type();
     1918        //              StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
     1919        //              if ( structType ) return structType->get_baseStruct();
     1920        //              UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
     1921        //              if ( unionType ) return unionType->get_baseUnion();
     1922        //
     1923        //              return NULL;
     1924        //      }
     1925        //
     1926        //      /// Finds the declaration with the given name, returning decls.end() if none such
     1927        //      std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
     1928        //              for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     1929        //                      if ( (*decl)->get_name() == name ) return decl;
     1930        //              }
     1931        //              return decls.end();
     1932        //      }
     1933        //
     1934        //      Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
     1935        //              // mutate, exiting early if no longer MemberExpr
     1936        //              Expression *expr = Mutator::mutate( memberExpr );
     1937        //              memberExpr = dynamic_cast< MemberExpr* >( expr );
     1938        //              if ( ! memberExpr ) return expr;
     1939        //
     1940        //              // get declaration of member and base declaration of member, exiting early if not found
     1941        //              AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
     1942        //              if ( ! memberBase ) return memberExpr;
     1943        //              DeclarationWithType *memberDecl = memberExpr->get_member();
     1944        //              std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
     1945        //              if ( baseIt == memberBase->get_members().end() ) return memberExpr;
     1946        //              DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
     1947        //              if ( ! baseDecl ) return memberExpr;
     1948        //
     1949        //              // check if stated type of the member is not the type of the member's declaration; if so, need a cast
     1950        //              // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
     1951        //              SymTab::Indexer dummy;
     1952        //              if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
     1953        //              else return new CastExpr( memberExpr, memberDecl->get_type() );
     1954        //      }
     1955
     1956                void GenericInstantiator::doBeginScope() {
     1957                        DeclMutator::doBeginScope();
     1958                        instantiations.beginScope();
     1959                }
     1960
     1961                void GenericInstantiator::doEndScope() {
     1962                        DeclMutator::doEndScope();
     1963                        instantiations.endScope();
     1964                }
     1965
     1966////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
     1967
     1968                void PolyGenericCalculator::beginTypeScope( Type *ty ) {
     1969                        scopeTyVars.beginScope();
     1970                        makeTyVarMap( ty, scopeTyVars );
     1971                }
     1972
     1973                void PolyGenericCalculator::endTypeScope() {
     1974                        scopeTyVars.endScope();
     1975                }
     1976
     1977                template< typename DeclClass >
     1978                DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
     1979                        beginTypeScope( type );
     1980                        knownLayouts.beginScope();
     1981                        knownOffsets.beginScope();
     1982
     1983                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
     1984
     1985                        knownOffsets.endScope();
     1986                        knownLayouts.endScope();
     1987                        endTypeScope();
     1988                        return ret;
     1989                }
     1990
     1991                ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
     1992                        return handleDecl( objectDecl, objectDecl->get_type() );
     1993                }
     1994
     1995                DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
     1996                        return handleDecl( functionDecl, functionDecl->get_functionType() );
     1997                }
     1998
     1999                TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
     2000                        return handleDecl( typedefDecl, typedefDecl->get_base() );
     2001                }
     2002
     2003                TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
     2004                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     2005                        return Mutator::mutate( typeDecl );
     2006                }
     2007
     2008                Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
     2009                        beginTypeScope( pointerType );
     2010
     2011                        Type *ret = Mutator::mutate( pointerType );
     2012
     2013                        endTypeScope();
     2014                        return ret;
     2015                }
     2016
     2017                Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
     2018                        beginTypeScope( funcType );
     2019
     2020                        // make sure that any type information passed into the function is accounted for
     2021                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
     2022                                // condition here duplicates that in Pass2::mutate( FunctionType* )
     2023                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     2024                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     2025                                        knownLayouts.insert( mangleType( polyType ) );
     2026                                }
     2027                        }
     2028
     2029                        Type *ret = Mutator::mutate( funcType );
     2030
     2031                        endTypeScope();
     2032                        return ret;
     2033                }
     2034
     2035                Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
     2036                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
     2037                                if ( findGeneric( objectDecl->get_type() ) ) {
     2038                                        // change initialization of a polymorphic value object
     2039                                        // to allocate storage with alloca
     2040                                        Type *declType = objectDecl->get_type();
     2041                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
     2042                                        alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) );
     2043
     2044                                        delete objectDecl->get_init();
     2045
     2046                                        std::list<Expression*> designators;
     2047                                        objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed
     2048                                }
     2049                        }
     2050                        return Mutator::mutate( declStmt );
     2051                }
     2052
     2053                /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
     2054                long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
     2055                        long i = 0;
     2056                        for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
     2057                                if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
     2058
     2059                                if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
     2060                                        if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
     2061                                             || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
     2062                                        else continue;
     2063                                } else return i;
     2064                        }
     2065                        return -1;
     2066                }
     2067
     2068                /// Returns an index expression into the offset array for a type
     2069                Expression *makeOffsetIndex( Type *objectType, long i ) {
     2070                        std::stringstream offset_namer;
     2071                        offset_namer << i;
     2072                        ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
     2073                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
     2074                        fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
     2075                        fieldOffset->get_args().push_back( fieldIndex );
     2076                        return fieldOffset;
     2077                }
     2078
     2079                /// Returns an expression dereferenced n times
     2080                Expression *makeDerefdVar( Expression *derefdVar, long n ) {
     2081                        for ( int i = 1; i < n; ++i ) {
     2082                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     2083                                derefExpr->get_args().push_back( derefdVar );
     2084                                // xxx - should set results on derefExpr
     2085                                derefdVar = derefExpr;
     2086                        }
     2087                        return derefdVar;
     2088                }
     2089
     2090                Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
     2091                        // mutate, exiting early if no longer MemberExpr
     2092                        Expression *expr = Mutator::mutate( memberExpr );
     2093                        memberExpr = dynamic_cast< MemberExpr* >( expr );
     2094                        if ( ! memberExpr ) return expr;
     2095
     2096                        // get declaration for base struct, exiting early if not found
     2097                        int varDepth;
     2098                        VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
     2099                        if ( ! varExpr ) return memberExpr;
     2100                        ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
     2101                        if ( ! objectDecl ) return memberExpr;
     2102
     2103                        // only mutate member expressions for polymorphic types
     2104                        int tyDepth;
     2105                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
     2106                        if ( ! objectType ) return memberExpr;
     2107                        findGeneric( objectType ); // ensure layout for this type is available
     2108
     2109                        Expression *newMemberExpr = 0;
     2110                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
     2111                                // look up offset index
     2112                                long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
     2113                                if ( i == -1 ) return memberExpr;
     2114
     2115                                // replace member expression with pointer to base plus offset
     2116                                UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
     2117                                fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
     2118                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
     2119                                newMemberExpr = fieldLoc;
     2120                        } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
     2121                                // union members are all at offset zero, so build appropriately-dereferenced variable
     2122                                newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth );
     2123                        } else return memberExpr;
     2124                        assert( newMemberExpr );
     2125
     2126                        Type *memberType = memberExpr->get_member()->get_type();
     2127                        if ( ! isPolyType( memberType, scopeTyVars ) ) {
     2128                                // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
     2129                                CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
     2130                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     2131                                derefExpr->get_args().push_back( ptrCastExpr );
     2132                                newMemberExpr = derefExpr;
     2133                        }
     2134
     2135                        delete memberExpr;
     2136                        return newMemberExpr;
     2137                }
     2138
     2139                ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
     2140                        ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
     2141                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     2142                        return newObj;
     2143                }
     2144
     2145                void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
     2146                        for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     2147                                if ( findGeneric( *param ) ) {
     2148                                        // push size/align vars for a generic parameter back
     2149                                        std::string paramName = mangleType( *param );
     2150                                        layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
     2151                                        layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
     2152                                } else {
     2153                                        layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
     2154                                        layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
     2155                                }
     2156                        }
     2157                }
     2158
     2159                /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
     2160                bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
     2161                        bool hasDynamicLayout = false;
     2162
     2163                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     2164                        std::list< Expression* >::const_iterator typeParam = typeParams.begin();
     2165                        for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
     2166                                // skip non-otype parameters
     2167                                if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
     2168                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
     2169                                assert( typeExpr && "all otype parameters should be type expressions" );
     2170
     2171                                Type *type = typeExpr->get_type();
     2172                                out.push_back( type );
     2173                                if ( isPolyType( type ) ) hasDynamicLayout = true;
     2174                        }
     2175                        assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
     2176
     2177                        return hasDynamicLayout;
     2178                }
     2179
     2180                bool PolyGenericCalculator::findGeneric( Type *ty ) {
     2181                        ty = replaceTypeInst( ty, env );
     2182
     2183                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
     2184                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     2185                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
     2186                                        return true;
     2187                                }
     2188                                return false;
     2189                        } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
     2190                                // check if this type already has a layout generated for it
     2191                                std::string typeName = mangleType( ty );
     2192                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2193
     2194                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2195                                std::list< Type* > otypeParams;
     2196                                if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
     2197
     2198                                // insert local variables for layout and generate call to layout function
     2199                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2200                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2201
     2202                                int n_members = structTy->get_baseStruct()->get_members().size();
     2203                                if ( n_members == 0 ) {
     2204                                        // all empty structs have the same layout - size 1, align 1
     2205                                        makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
     2206                                        makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
     2207                                        // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
     2208                                } else {
     2209                                        ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2210                                        ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2211                                        ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
     2212
     2213                                        // generate call to layout function
     2214                                        UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
     2215                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2216                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2217                                        layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
     2218                                        addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2219
     2220                                        stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2221                                }
     2222
     2223                                return true;
     2224                        } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
     2225                                // check if this type already has a layout generated for it
     2226                                std::string typeName = mangleType( ty );
     2227                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2228
     2229                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2230                                std::list< Type* > otypeParams;
     2231                                if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
     2232
     2233                                // insert local variables for layout and generate call to layout function
     2234                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2235                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2236
     2237                                ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2238                                ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2239
     2240                                // generate call to layout function
     2241                                UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
     2242                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2243                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2244                                addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2245
     2246                                stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2247
     2248                                return true;
     2249                        }
     2250
     2251                        return false;
     2252                }
     2253
     2254                Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
     2255                        Type *ty = sizeofExpr->get_type();
     2256                        if ( findGeneric( ty ) ) {
     2257                                Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) );
     2258                                delete sizeofExpr;
     2259                                return ret;
     2260                        }
     2261                        return sizeofExpr;
     2262                }
     2263
     2264                Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
     2265                        Type *ty = alignofExpr->get_type();
     2266                        if ( findGeneric( ty ) ) {
     2267                                Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
     2268                                delete alignofExpr;
     2269                                return ret;
     2270                        }
     2271                        return alignofExpr;
     2272                }
     2273
     2274                Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
     2275                        // mutate, exiting early if no longer OffsetofExpr
     2276                        Expression *expr = Mutator::mutate( offsetofExpr );
     2277                        offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
     2278                        if ( ! offsetofExpr ) return expr;
     2279
     2280                        // only mutate expressions for polymorphic structs/unions
     2281                        Type *ty = offsetofExpr->get_type();
     2282                        if ( ! findGeneric( ty ) ) return offsetofExpr;
     2283
     2284                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
     2285                                // replace offsetof expression by index into offset array
     2286                                long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
     2287                                if ( i == -1 ) return offsetofExpr;
     2288
     2289                                Expression *offsetInd = makeOffsetIndex( ty, i );
     2290                                delete offsetofExpr;
     2291                                return offsetInd;
     2292                        } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
     2293                                // all union members are at offset zero
     2294                                delete offsetofExpr;
     2295                                return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "0" ) );
     2296                        } else return offsetofExpr;
     2297                }
     2298
     2299                Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
     2300                        StructInstType *ty = offsetPackExpr->get_type();
     2301
     2302                        Expression *ret = 0;
     2303                        if ( findGeneric( ty ) ) {
     2304                                // pull offset back from generated type information
     2305                                ret = new NameExpr( offsetofName( mangleType( ty ) ) );
     2306                        } else {
     2307                                std::string offsetName = offsetofName( mangleType( ty ) );
     2308                                if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     2309                                        // use the already-generated offsets for this type
     2310                                        ret = new NameExpr( offsetName );
     2311                                } else {
     2312                                        knownOffsets.insert( offsetName );
     2313
     2314                                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
     2315                                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2316
     2317                                        // build initializer list for offset array
     2318                                        std::list< Initializer* > inits;
     2319                                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
     2320                                                DeclarationWithType *memberDecl;
     2321                                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
     2322                                                        memberDecl = origMember->clone();
     2323                                                } else {
     2324                                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
     2325                                                }
     2326                                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
     2327                                        }
     2328
     2329                                        // build the offset array and replace the pack with a reference to it
     2330                                        ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
     2331                                                        new ListInit( inits ) );
     2332                                        ret = new VariableExpr( offsetArray );
     2333                                }
     2334                        }
     2335
     2336                        delete offsetPackExpr;
     2337                        return ret;
     2338                }
     2339
     2340                void PolyGenericCalculator::doBeginScope() {
     2341                        knownLayouts.beginScope();
     2342                        knownOffsets.beginScope();
     2343                }
     2344
     2345                void PolyGenericCalculator::doEndScope() {
     2346                        knownLayouts.endScope();
     2347                        knownOffsets.endScope();
    10222348                }
    10232349
     
    10262352                template< typename DeclClass >
    10272353                DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
    1028                         TyVarMap oldtyVars = scopeTyVars;
     2354                        scopeTyVars.beginScope();
    10292355                        makeTyVarMap( type, scopeTyVars );
    1030  
     2356
    10312357                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    10322358                        ScrubTyVars::scrub( decl, scopeTyVars );
    10332359
    1034                         scopeTyVars = oldtyVars;
     2360                        scopeTyVars.endScope();
    10352361                        return ret;
    10362362                }
     
    10492375
    10502376                TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
    1051 ///   Initializer *init = 0;
    1052 ///   std::list< Expression *> designators;
    1053 ///   scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    1054 ///   if ( typeDecl->get_base() ) {
    1055 ///     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
    1056 ///   }
    1057 ///   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
     2377//   Initializer *init = 0;
     2378//   std::list< Expression *> designators;
     2379//   scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     2380//   if ( typeDecl->get_base() ) {
     2381//     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
     2382//   }
     2383//   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
    10582384
    10592385                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     
    10622388
    10632389                Type * Pass3::mutate( PointerType *pointerType ) {
    1064                         TyVarMap oldtyVars = scopeTyVars;
     2390                        scopeTyVars.beginScope();
    10652391                        makeTyVarMap( pointerType, scopeTyVars );
    1066  
     2392
    10672393                        Type *ret = Mutator::mutate( pointerType );
    1068  
    1069                         scopeTyVars = oldtyVars;
     2394
     2395                        scopeTyVars.endScope();
    10702396                        return ret;
    10712397                }
    10722398
    10732399                Type * Pass3::mutate( FunctionType *functionType ) {
    1074                         TyVarMap oldtyVars = scopeTyVars;
     2400                        scopeTyVars.beginScope();
    10752401                        makeTyVarMap( functionType, scopeTyVars );
    1076  
     2402
    10772403                        Type *ret = Mutator::mutate( functionType );
    1078  
    1079                         scopeTyVars = oldtyVars;
     2404
     2405                        scopeTyVars.endScope();
    10802406                        return ret;
    1081                 }
    1082 
    1083                 Statement *Pass3::mutate( DeclStmt *declStmt ) {
    1084                         if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    1085                                 if ( isPolyVal( objectDecl->get_type(), scopeTyVars ) ) {
    1086                                         // change initialization of a polymorphic value object
    1087                                         // to allocate storage with alloca
    1088                                         TypeInstType *typeInst = dynamic_cast< TypeInstType *>( objectDecl->get_type() );
    1089                                         assert( typeInst );
    1090                                         UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
    1091                                         alloc->get_args().push_back( new NameExpr( typeInst->get_name() ) );
    1092 
    1093                                         delete objectDecl->get_init();
    1094 
    1095                                         std::list<Expression*> designators;
    1096                                         objectDecl->set_init( new SingleInit( alloc, designators ) );
    1097                                 }
    1098                         }
    1099                         return Mutator::mutate( declStmt );
    11002407                }
    11012408        } // anonymous namespace
Note: See TracChangeset for help on using the changeset viewer.