Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r9799ec8 rc29d9ce  
    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 : Peter A. Buhr
    12 // Last Modified On : Wed Jun 29 21:43:03 2016
    13 // Update Count     : 296
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Tue Aug 11 16:22:35 2015
     13// Update Count     : 89
    1414//
    1515
    16 #include <algorithm>
    17 #include <iterator>
    18 #include <list>
    19 #include <map>
    2016#include <set>
    2117#include <stack>
    2218#include <string>
    23 #include <utility>
    24 #include <vector>
     19#include <iterator>
     20#include <algorithm>
    2521#include <cassert>
    2622
    2723#include "Box.h"
    28 #include "DeclMutator.h"
    2924#include "PolyMutator.h"
    3025#include "FindFunction.h"
    31 #include "ScopedMap.h"
    32 #include "ScopedSet.h"
    3326#include "ScrubTyVars.h"
    3427
    3528#include "Parser/ParseNode.h"
    3629
    37 #include "SynTree/Constant.h"
    38 #include "SynTree/Declaration.h"
     30#include "SynTree/Type.h"
    3931#include "SynTree/Expression.h"
    4032#include "SynTree/Initializer.h"
     33#include "SynTree/Statement.h"
    4134#include "SynTree/Mutator.h"
    42 #include "SynTree/Statement.h"
    43 #include "SynTree/Type.h"
    44 #include "SynTree/TypeSubstitution.h"
    4535
    4636#include "ResolvExpr/TypeEnvironment.h"
    47 #include "ResolvExpr/TypeMap.h"
    48 #include "ResolvExpr/typeops.h"
    49 
    50 #include "SymTab/Indexer.h"
     37
    5138#include "SymTab/Mangler.h"
    5239
    53 #include "Common/SemanticError.h"
    54 #include "Common/UniqueName.h"
    55 #include "Common/utility.h"
     40#include "SemanticError.h"
     41#include "UniqueName.h"
     42#include "utility.h"
    5643
    5744#include <ext/functional> // temporary
     
    6148                const std::list<Label> noLabels;
    6249
    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
    16450                class Pass1 : public PolyMutator {
    16551                  public:
     
    17258                        virtual Expression *mutate( CommaExpr *commaExpr );
    17359                        virtual Expression *mutate( ConditionalExpr *condExpr );
    174                         virtual Statement * mutate( ReturnStmt *returnStmt );
     60                        virtual Statement *mutate(ReturnStmt *catchStmt);
    17561                        virtual Type *mutate( PointerType *pointerType );
    176                         virtual Type * mutate( FunctionType *functionType );
    177 
     62                        virtual Type *mutate( FunctionType *pointerType );
     63 
    17864                        virtual void doBeginScope();
    17965                        virtual void doEndScope();
    18066                  private:
    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
     67                        void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    18668                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, 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 );
     69                        Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg );
    19470                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    19571                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
    19672                        void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    19773                        void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
    198                         /// Stores assignment operators from assertion list in local map of assignment operations
    199                         void findTypeOps( const std::list< TypeDecl *> &forall );
     74                        void findAssignOps( const std::list< TypeDecl *> &forall );
    20075                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    20176                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
    202                         /// Replaces intrinsic operator functions with their arithmetic desugaring
    20377                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
    204                         /// Inserts a new temporary variable into the current scope with an auto-generated name
    20578                        ObjectDecl *makeTemporary( Type *type );
    20679
    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 
     80                        typedef std::map< std::string, FunctionDecl *> AdapterMap;
     81                        std::map< std::string, DeclarationWithType *> assignOps;
     82                        std::stack< AdapterMap > adapters;
    21783                        DeclarationWithType *retval;
    21884                        bool useRetval;
     
    22086                };
    22187
    222                 /// * Moves polymorphic returns in function types to pointer-type parameters
    223                 /// * adds type size and assertion parameters to parameter lists
    22488                class Pass2 : public PolyMutator {
    22589                  public:
     90                        Pass2();
    22691                        template< typename DeclClass >
    22792                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    23297                        virtual Type *mutate( PointerType *pointerType );
    23398                        virtual Type *mutate( FunctionType *funcType );
    234 
    23599                  private:
    236100                        void addAdapters( FunctionType *functionType );
    237 
     101 
    238102                        std::map< UniqueId, std::string > adapterName;
    239103                };
    240104
    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:
     105                class Pass3 : public PolyMutator {
     106                  public:
    275107                        template< typename DeclClass >
    276108                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    282114                        virtual Type *mutate( PointerType *pointerType );
    283115                        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 );
    321116                  private:
    322117                };
     
    324119        } // anonymous namespace
    325120
    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
     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
    346127                } // for
    347                 if ( ! errors.isEmpty() ) {
    348                         throw errors;
    349                 } // if
    350128        }
    351129
    352130        void box( std::list< Declaration *>& translationUnit ) {
    353                 LayoutFunctionBuilder layoutBuilder;
    354131                Pass1 pass1;
    355132                Pass2 pass2;
    356                 GenericInstantiator instantiator;
    357                 PolyGenericCalculator polyCalculator;
    358133                Pass3 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 );
     134                mutateAll( translationUnit, pass1 );
     135                mutateAll( translationUnit, pass2 );
     136                mutateAll( translationUnit, pass3 );
    366137        }
    367138
    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 
    567139        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    568140
    569141        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 
    602142                std::string makeAdapterName( const std::string &mangleName ) {
    603143                        return "_adapter" + mangleName;
    604144                }
    605145
    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;
     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;
    615157                                                } // if
     158                                        } // for
     159                                        if ( ! doTransform && otherTyVars.find( typeInst->get_name() ) != otherTyVars.end() ) {
     160                                                doTransform = true;
    616161                                        } // if
    617162                                } // if
    618163                        } // if
    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;
     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;
    631190                                                                } // if
    632191                                                        } // if
     
    635194                                } // if
    636195                        } // if
    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();
     196                        return false;
     197                }
     198
     199                void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
     200                        assignOps.clear();
    731201                        for ( std::list< TypeDecl *>::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
    732202                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    733203                                        std::string typeName;
    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;
     204                                        if ( checkAssignment( *assert, typeName ) ) {
     205                                                assignOps[ typeName ] = *assert;
    742206                                        } // if
    743207                                } // for
     
    746210
    747211                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    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 
     212                        if ( functionDecl->get_statements() ) {
     213                                TyVarMap oldtyVars = scopeTyVars;
    775214                                DeclarationWithType *oldRetval = retval;
    776215                                bool oldUseRetval = useRetval;
    777 
    778                                 // process polymorphic return value
     216       
    779217                                retval = 0;
    780                                 if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
     218                                std::string typeName;
     219                                if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
    781220                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    782 
     221 
    783222                                        // give names to unnamed return values
    784223                                        if ( retval->get_name() == "" ) {
     
    787226                                        } // if
    788227                                } // if
    789 
    790                                 FunctionType *functionType = functionDecl->get_functionType();
     228       
     229                                scopeTyVars.clear();
     230///     std::cerr << "clear\n";
    791231                                makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
    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 
     232                                findAssignOps( functionDecl->get_functionType()->get_forall() );
    813233                                functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
    814 
    815                                 scopeTyVars.endScope();
    816                                 assignOps.endScope();
    817                                 ctorOps.endScope();
    818                                 copyOps.endScope();
    819                                 dtorOps.endScope();
     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";
    820241                                retval = oldRetval;
    821242                                useRetval = oldUseRetval;
    822                                 doEndScope();
     243                                // doEndScope();
    823244                        } // if
    824245                        return functionDecl;
     
    826247
    827248                TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
     249///     std::cerr << "add " << typeDecl->get_name() << "\n";
    828250                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    829251                        return Mutator::mutate( typeDecl );
     
    850272                }
    851273
    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
     274                void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    880275                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
    881276                                ResolvExpr::EqvClass eqvClass;
     
    886281                                                arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
    887282                                                arg++;
    888                                                 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
    889                                                 arg++;
    890283                                        } else {
    891                                                 /// xxx - should this be an assertion?
    892                                                 throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr );
     284                                                throw SemanticError( "unbound type variable in application ", appExpr );
    893285                                        } // if
    894286                                } // if
    895287                        } // 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                         }
    918288                }
    919289
     
    924294                }
    925295
     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
     302                                } // 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
    926313                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 );
    969                                 } // if
    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 ) {
     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;
    988337                        assert( env );
    989                         Type *concrete = replaceWithConcrete( appExpr, polyType );
    990                         // add out-parameter for return value
     338                        Type *concrete = env->lookup( typeName );
     339                        if ( concrete == 0 ) {
     340                                throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr );
     341                        } // if
    991342                        return addRetParam( appExpr, function, concrete, arg );
    992343                }
     
    994345                Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
    995346                        Expression *ret = appExpr;
    996                         if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
     347                        if ( ! function->get_returnVals().empty() && isPolyVal( function->get_returnVals().front()->get_type(), tyVars ) ) {
    997348                                ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg );
    998349                        } // if
    999                         std::string mangleName = mangleAdapterName( function, tyVars );
     350                        std::string mangleName = SymTab::Mangler::mangle( function );
    1000351                        std::string adapterName = makeAdapterName( mangleName );
    1001352
    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 ) );
     353                        appExpr->get_args().push_front( appExpr->get_function() );
    1005354                        appExpr->set_function( new NameExpr( adapterName ) );
    1006 
     355 
    1007356                        return ret;
    1008357                }
     
    1010359                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    1011360                        assert( ! arg->get_results().empty() );
    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!
     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!
    1015366                                        return;
    1016367                                } else if ( arg->get_results().front()->get_isLvalue() ) {
    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                                         }
     368                                        // VariableExpr and MemberExpr are lvalues
     369                                        arg = new AddressExpr( arg );
    1024370                                } else {
    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 );
     371                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 );
    1029372                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    1030373                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     
    1036379                                } // if
    1037380                        } // if
    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.
     381///   }
     382                }
     383
    1043384                void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
    1044                         Type * newType = formal->clone();
    1045                         if ( getFunctionType( newType ) ) {
    1046                                 newType = ScrubTyVars::scrub( newType, 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() ) {
    1047391                                actual = new CastExpr( actual, newType );
     392                        } else {
     393                                delete newType;
    1048394                        } // if
    1049395                }
    1050396
    1051397                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 );
    1052400                        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 );
    1053405                                assert( arg != appExpr->get_args().end() );
    1054406                                addCast( *arg, (*param)->get_type(), exprTyVars );
     
    1062414                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
    1063415                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
    1064                                         assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
     416                                        assert( inferParam != appExpr->get_inferParams().end() );
    1065417                                        Expression *newExpr = inferParam->second.expr->clone();
    1066418                                        addCast( newExpr, (*assert)->get_type(), tyVars );
     
    1085437                        // actually make the adapter type
    1086438                        FunctionType *adapter = adaptee->clone();
    1087                         if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
     439                        if ( ! adapter->get_returnVals().empty() && isPolyVal( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
    1088440                                makeRetParm( adapter );
    1089441                        } // if
     
    1095447                        assert( param );
    1096448                        assert( arg );
    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
     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///     }
    1104464                        } // if
    1105465                        return new VariableExpr( param );
     
    1116476                        } // for
    1117477                }
     478
     479
    1118480
    1119481                FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     
    1124486                        ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
    1125487                        Statement *bodyStmt;
    1126 
     488 
    1127489                        std::list< TypeDecl *>::iterator tyArg = realType->get_forall().begin();
    1128490                        std::list< TypeDecl *>::iterator tyParam = adapterType->get_forall().begin();
     
    1138500                                } // for
    1139501                        } // for
    1140 
     502 
    1141503                        std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
    1142504                        std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
    1143505                        std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
    1144                         param++;                // skip adaptee parameter in the adapter type
     506                        param++;                // skip adaptee parameter
    1145507                        if ( realType->get_returnVals().empty() ) {
    1146                                 // void return
    1147508                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
    1148509                                bodyStmt = new ExprStmt( noLabels, adapteeApp );
    1149                         } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
    1150                                 // return type T
     510                        } else if ( isPolyVal( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
    1151511                                if ( (*param)->get_name() == "" ) {
    1152512                                        (*param)->set_name( "_ret" );
     
    1184544                        } // for
    1185545
    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
     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
    1188549                        std::set< std::string > adaptersDone;
    1189550
     
    1193554                                std::string mangleName = SymTab::Mangler::mangle( realFunction );
    1194555
    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.
     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.
    1197558                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
     559                                        std::string mangleName = SymTab::Mangler::mangle( realFunction );
    1198560                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
    1199 
    1200                                         // apply substitution to type variables to figure out what the adapter's type should look like
     561                                       
     562                                        // apply substitution to type variables to figure out what the
     563                                        // adapter's type should look like
    1201564                                        assert( env );
    1202565                                        env->apply( realFunction );
    1203566                                        mangleName = SymTab::Mangler::mangle( realFunction );
    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 ) );
     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 ) );
    1214595                                        } // 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 ) );
    1219596                                } // if
    1220597                        } // for
    1221                 } // passAdapters
    1222 
    1223                 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
     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 ) {
    1224627                        NameExpr *opExpr;
    1225628                        if ( isIncr ) {
     
    1234637                                addAssign->get_args().push_back( appExpr->get_args().front() );
    1235638                        } // if
    1236                         addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
     639                        addAssign->get_args().push_back( new NameExpr( polyName ) );
    1237640                        addAssign->get_results().front() = appExpr->get_results().front()->clone();
    1238641                        if ( appExpr->get_env() ) {
     
    1251654                                                assert( ! appExpr->get_results().empty() );
    1252655                                                assert( appExpr->get_args().size() == 2 );
    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
     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 );
    1256659                                                UntypedExpr *ret = 0;
    1257                                                 if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
     660                                                if ( typeInst1 || typeInst2 ) {
    1258661                                                        ret = new UntypedExpr( new NameExpr( "?+?" ) );
    1259662                                                } // if
    1260                                                 if ( baseType1 ) {
     663                                                if ( typeInst1 ) {
    1261664                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    1262665                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1263                                                         multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
     666                                                        multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
    1264667                                                        ret->get_args().push_back( appExpr->get_args().front() );
    1265668                                                        ret->get_args().push_back( multiply );
    1266                                                 } else if ( baseType2 ) {
     669                                                } else if ( typeInst2 ) {
    1267670                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    1268671                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    1269                                                         multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
     672                                                        multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );
    1270673                                                        ret->get_args().push_back( multiply );
    1271674                                                        ret->get_args().push_back( appExpr->get_args().back() );
    1272675                                                } // if
    1273                                                 if ( baseType1 || baseType2 ) {
     676                                                if ( typeInst1 || typeInst2 ) {
    1274677                                                        ret->get_results().push_front( appExpr->get_results().front()->clone() );
    1275678                                                        if ( appExpr->get_env() ) {
     
    1284687                                                assert( ! appExpr->get_results().empty() );
    1285688                                                assert( ! appExpr->get_args().empty() );
    1286                                                 if ( isPolyType( appExpr->get_results().front(), scopeTyVars, env ) ) {
     689                                                if ( isPolyType( appExpr->get_results().front(), env, scopeTyVars ) ) {
    1287690                                                        Expression *ret = appExpr->get_args().front();
    1288691                                                        delete ret->get_results().front();
     
    1299702                                                assert( ! appExpr->get_results().empty() );
    1300703                                                assert( appExpr->get_args().size() == 1 );
    1301                                                 if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
     704                                                if ( TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars ) ) {
    1302705                                                        Type *tempType = appExpr->get_results().front()->clone();
    1303706                                                        if ( env ) {
     
    1313716                                                                assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
    1314717                                                        } // if
    1315                                                         CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
     718                                                        CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "?++" ) );
    1316719                                                        return new CommaExpr( firstComma, tempExpr );
    1317720                                                } // if
     
    1319722                                                assert( ! appExpr->get_results().empty() );
    1320723                                                assert( appExpr->get_args().size() == 1 );
    1321                                                 if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
    1322                                                         return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
     724                                                if ( TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars ) ) {
     725                                                        return makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "++?" );
    1323726                                                } // if
    1324727                                        } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
    1325728                                                assert( ! appExpr->get_results().empty() );
    1326729                                                assert( appExpr->get_args().size() == 2 );
    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 ) {
     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 ) {
    1330733                                                        UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
    1331734                                                        divide->get_args().push_back( appExpr );
    1332                                                         divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
     735                                                        divide->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
    1333736                                                        divide->get_results().push_front( appExpr->get_results().front()->clone() );
    1334737                                                        if ( appExpr->get_env() ) {
     
    1337740                                                        } // if
    1338741                                                        return divide;
    1339                                                 } else if ( baseType1 ) {
     742                                                } else if ( typeInst1 ) {
    1340743                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    1341744                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1342                                                         multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
     745                                                        multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );
    1343746                                                        appExpr->get_args().back() = multiply;
    1344                                                 } else if ( baseType2 ) {
     747                                                } else if ( typeInst2 ) {
    1345748                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    1346749                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    1347                                                         multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
     750                                                        multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );
    1348751                                                        appExpr->get_args().front() = multiply;
    1349752                                                } // if
     
    1351754                                                assert( ! appExpr->get_results().empty() );
    1352755                                                assert( appExpr->get_args().size() == 2 );
    1353                                                 Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env );
    1354                                                 if ( baseType ) {
     756                                                TypeInstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars );
     757                                                if ( typeInst ) {
    1355758                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    1356759                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    1357                                                         multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
     760                                                        multiply->get_args().push_back( new NameExpr( typeInst->get_name() ) );
    1358761                                                        appExpr->get_args().back() = multiply;
    1359762                                                } // if
     
    1366769
    1367770                Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
    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";
     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";
    1373776                        bool oldUseRetval = useRetval;
    1374777                        useRetval = false;
     
    1376779                        mutateAll( appExpr->get_args(), *this );
    1377780                        useRetval = oldUseRetval;
    1378 
     781 
    1379782                        assert( ! appExpr->get_function()->get_results().empty() );
    1380783                        PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
     
    1382785                        FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
    1383786                        assert( function );
    1384 
     787 
    1385788                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
    1386789                                return newExpr;
    1387790                        } // if
    1388 
     791 
    1389792                        Expression *ret = appExpr;
    1390 
     793 
    1391794                        std::list< Expression *>::iterator arg = appExpr->get_args().begin();
    1392795                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    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 );
     796 
     797                        std::string typeName;
     798                        if ( isPolyRet( function, typeName ) ) {
     799                                ret = addPolyRetParam( appExpr, function, typeName, arg );
    1400800                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    1401                                 // std::cerr << "needs adapter: ";
    1402                                 // printTyVarMap( std::cerr, scopeTyVars );
    1403                                 // std::cerr << *env << std::endl;
     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";
    1404806                                // change the application so it calls the adapter rather than the passed function
    1405807                                ret = applyAdapter( appExpr, function, arg, scopeTyVars );
    1406808                        } // if
    1407809                        arg = appExpr->get_args().begin();
    1408 
    1409                         passTypeVars( appExpr, polyRetType, arg, exprTyVars );
     810 
     811                        TyVarMap exprTyVars;
     812                        makeTyVarMap( function, exprTyVars );
     813 
     814                        passTypeVars( appExpr, arg, exprTyVars );
    1410815                        addInferredParams( appExpr, function, arg, exprTyVars );
    1411816
    1412817                        arg = paramBegin;
    1413 
     818 
    1414819                        boxParams( appExpr, function, arg, exprTyVars );
     820
    1415821                        passAdapters( appExpr, function, exprTyVars );
    1416822
     
    1419825
    1420826                Expression *Pass1::mutate( UntypedExpr *expr ) {
    1421                         if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
     827                        if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), env, scopeTyVars ) ) {
    1422828                                if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
    1423829                                        if ( name->get_name() == "*?" ) {
     
    1434840                Expression *Pass1::mutate( AddressExpr *addrExpr ) {
    1435841                        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 );
    1457842                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
    1458                         if ( polytype || needs ) {
     843                        if ( isPolyType( addrExpr->get_arg()->get_results().front(), env, scopeTyVars ) ) {
    1459844                                Expression *ret = addrExpr->get_arg();
    1460845                                delete ret->get_results().front();
     
    1468853                }
    1469854
    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;
     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() );
     871                                        if ( assignIter == assignOps.end() ) {
     872                                                throw SemanticError( "Attempt to return dtype or ftype object in ", retStmt->get_expr() );
     873                                        } // 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 );
    1486886                        } 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() );
    1516                                         if ( assignIter == assignOps.end() ) {
    1517                                                 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    1518                                         } // if
    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 );
    1589                         } else {
    1590                                 returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
    1591                         } // if
    1592                         return returnStmt;
     887                                retStmt->set_expr( mutateExpression( retStmt->get_expr() ) );
     888                        } // if
     889                        return retStmt;
    1593890                }
    1594891
    1595892                Type * Pass1::mutate( PointerType *pointerType ) {
    1596                         scopeTyVars.beginScope();
     893                        TyVarMap oldtyVars = scopeTyVars;
    1597894                        makeTyVarMap( pointerType, scopeTyVars );
    1598 
     895 
    1599896                        Type *ret = Mutator::mutate( pointerType );
    1600 
    1601                         scopeTyVars.endScope();
     897 
     898                        scopeTyVars = oldtyVars;
    1602899                        return ret;
    1603900                }
    1604901
    1605902                Type * Pass1::mutate( FunctionType *functionType ) {
    1606                         scopeTyVars.beginScope();
     903                        TyVarMap oldtyVars = scopeTyVars;
    1607904                        makeTyVarMap( functionType, scopeTyVars );
    1608 
     905 
    1609906                        Type *ret = Mutator::mutate( functionType );
    1610 
    1611                         scopeTyVars.endScope();
     907 
     908                        scopeTyVars = oldtyVars;
    1612909                        return ret;
    1613910                }
    1614911
    1615912                void Pass1::doBeginScope() {
    1616                         adapters.beginScope();
    1617                         scopedAssignOps.beginScope();
    1618                         scopedCtorOps.beginScope();
    1619                         scopedCopyOps.beginScope();
    1620                         scopedDtorOps.beginScope();
     913                        // actually, maybe this could (should?) push
     914                        // a copy of the current map
     915                        adapters.push(AdapterMap());
    1621916                }
    1622917
    1623918                void Pass1::doEndScope() {
    1624                         adapters.endScope();
    1625                         scopedAssignOps.endScope();
    1626                         scopedCtorOps.endScope();
    1627                         scopedCopyOps.endScope();
    1628                         scopedDtorOps.endScope();
     919                        adapters.pop();
    1629920                }
    1630921
    1631922////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
     923
     924                Pass2::Pass2() {}
    1632925
    1633926                void Pass2::addAdapters( FunctionType *functionType ) {
     
    1641934                        std::set< std::string > adaptersDone;
    1642935                        for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    1643                                 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     936                                std::string mangleName = SymTab::Mangler::mangle( *funType );
    1644937                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    1645938                                        std::string adapterName = makeAdapterName( mangleName );
     
    1648941                                }
    1649942                        }
    1650 //  deleteAll( functions );
     943///  deleteAll( functions );
    1651944                }
    1652945
     
    1680973
    1681974                Type * Pass2::mutate( PointerType *pointerType ) {
    1682                         scopeTyVars.beginScope();
     975                        TyVarMap oldtyVars = scopeTyVars;
    1683976                        makeTyVarMap( pointerType, scopeTyVars );
    1684 
     977 
    1685978                        Type *ret = Mutator::mutate( pointerType );
    1686 
    1687                         scopeTyVars.endScope();
     979 
     980                        scopeTyVars = oldtyVars;
    1688981                        return ret;
    1689982                }
    1690983
    1691984                Type *Pass2::mutate( FunctionType *funcType ) {
    1692                         scopeTyVars.beginScope();
     985                        TyVarMap oldtyVars = scopeTyVars;
    1693986                        makeTyVarMap( funcType, scopeTyVars );
    1694 
    1695                         // move polymorphic return type to parameter list
    1696                         if ( isPolyRet( funcType ) ) {
     987 
     988                        std::string typeName;
     989                        if ( isPolyRet( funcType, typeName ) ) {
    1697990                                DeclarationWithType *ret = funcType->get_returnVals().front();
    1698991                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
     
    1700993                                funcType->get_returnVals().pop_front();
    1701994                        }
    1702 
    1703                         // add size/align and assertions for type parameters to parameter list
     995 
    1704996                        std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
    1705997                        std::list< DeclarationWithType *> inferredParams;
    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 );
     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 );
    17091000                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
    1710                                 ObjectDecl *sizeParm, *alignParm;
    1711                                 // add all size and alignment parameters to parameter list
     1001                                ObjectDecl *thisParm;
    17121002                                if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
    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 );
     1003                                        thisParm = newObj->clone();
     1004                                        thisParm->set_name( (*tyParm)->get_name() );
     1005                                        last = funcType->get_parameters().insert( last, thisParm );
    17241006                                        ++last;
    17251007                                }
    1726                                 // move all assertions into parameter list
    17271008                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
    1728 //      *assert = (*assert)->acceptMutator( *this );
     1009///      *assert = (*assert)->acceptMutator( *this );
    17291010                                        inferredParams.push_back( *assert );
    17301011                                }
    17311012                                (*tyParm)->get_assertions().clear();
    17321013                        }
    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
     1014                        delete newObj;
    17681015                        funcType->get_parameters().splice( last, inferredParams );
    17691016                        addAdapters( funcType );
    17701017                        mutateAll( funcType->get_returnVals(), *this );
    17711018                        mutateAll( funcType->get_parameters(), *this );
    1772 
    1773                         scopeTyVars.endScope();
     1019 
     1020                        scopeTyVars = oldtyVars;
    17741021                        return funcType;
    17751022                }
    17761023
    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                 }
     1024////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    19761025
    19771026                template< typename DeclClass >
    1978                 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
    1979                         beginTypeScope( type );
    1980                         knownLayouts.beginScope();
    1981                         knownOffsets.beginScope();
    1982 
     1027                DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
     1028                        TyVarMap oldtyVars = scopeTyVars;
     1029                        makeTyVarMap( type, scopeTyVars );
     1030 
    19831031                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    1984 
    1985                         knownOffsets.endScope();
    1986                         knownLayouts.endScope();
    1987                         endTypeScope();
     1032                        ScrubTyVars::scrub( decl, scopeTyVars );
     1033
     1034                        scopeTyVars = oldtyVars;
    19881035                        return ret;
    19891036                }
    19901037
    1991                 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
     1038                ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
    19921039                        return handleDecl( objectDecl, objectDecl->get_type() );
    19931040                }
    19941041
    1995                 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
     1042                DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
    19961043                        return handleDecl( functionDecl, functionDecl->get_functionType() );
    19971044                }
    19981045
    1999                 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
     1046                TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
    20001047                        return handleDecl( typedefDecl, typedefDecl->get_base() );
    20011048                }
    20021049
    2003                 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
     1050                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 );
     1058
    20041059                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    20051060                        return Mutator::mutate( typeDecl );
    20061061                }
    20071062
    2008                 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
    2009                         beginTypeScope( pointerType );
    2010 
     1063                Type * Pass3::mutate( PointerType *pointerType ) {
     1064                        TyVarMap oldtyVars = scopeTyVars;
     1065                        makeTyVarMap( pointerType, scopeTyVars );
     1066 
    20111067                        Type *ret = Mutator::mutate( pointerType );
    2012 
    2013                         endTypeScope();
     1068 
     1069                        scopeTyVars = oldtyVars;
    20141070                        return ret;
    20151071                }
    20161072
    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();
     1073                Type * Pass3::mutate( FunctionType *functionType ) {
     1074                        TyVarMap oldtyVars = scopeTyVars;
     1075                        makeTyVarMap( functionType, scopeTyVars );
     1076 
     1077                        Type *ret = Mutator::mutate( functionType );
     1078 
     1079                        scopeTyVars = oldtyVars;
    20321080                        return ret;
    20331081                }
    20341082
    2035                 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
     1083                Statement *Pass3::mutate( DeclStmt *declStmt ) {
    20361084                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    2037                                 if ( findGeneric( objectDecl->get_type() ) ) {
     1085                                if ( isPolyVal( objectDecl->get_type(), scopeTyVars ) ) {
    20381086                                        // change initialization of a polymorphic value object
    20391087                                        // to allocate storage with alloca
    2040                                         Type *declType = objectDecl->get_type();
     1088                                        TypeInstType *typeInst = dynamic_cast< TypeInstType *>( objectDecl->get_type() );
     1089                                        assert( typeInst );
    20411090                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
    2042                                         alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) );
     1091                                        alloc->get_args().push_back( new NameExpr( typeInst->get_name() ) );
    20431092
    20441093                                        delete objectDecl->get_init();
    20451094
    20461095                                        std::list<Expression*> designators;
    2047                                         objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed
     1096                                        objectDecl->set_init( new SingleInit( alloc, designators ) );
    20481097                                }
    20491098                        }
    20501099                        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();
    2348                 }
    2349 
    2350 ////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    2351 
    2352                 template< typename DeclClass >
    2353                 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
    2354                         scopeTyVars.beginScope();
    2355                         makeTyVarMap( type, scopeTyVars );
    2356 
    2357                         DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    2358                         ScrubTyVars::scrub( decl, scopeTyVars );
    2359 
    2360                         scopeTyVars.endScope();
    2361                         return ret;
    2362                 }
    2363 
    2364                 ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
    2365                         return handleDecl( objectDecl, objectDecl->get_type() );
    2366                 }
    2367 
    2368                 DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
    2369                         return handleDecl( functionDecl, functionDecl->get_functionType() );
    2370                 }
    2371 
    2372                 TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
    2373                         return handleDecl( typedefDecl, typedefDecl->get_base() );
    2374                 }
    2375 
    2376                 TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
    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 );
    2384 
    2385                         scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    2386                         return Mutator::mutate( typeDecl );
    2387                 }
    2388 
    2389                 Type * Pass3::mutate( PointerType *pointerType ) {
    2390                         scopeTyVars.beginScope();
    2391                         makeTyVarMap( pointerType, scopeTyVars );
    2392 
    2393                         Type *ret = Mutator::mutate( pointerType );
    2394 
    2395                         scopeTyVars.endScope();
    2396                         return ret;
    2397                 }
    2398 
    2399                 Type * Pass3::mutate( FunctionType *functionType ) {
    2400                         scopeTyVars.beginScope();
    2401                         makeTyVarMap( functionType, scopeTyVars );
    2402 
    2403                         Type *ret = Mutator::mutate( functionType );
    2404 
    2405                         scopeTyVars.endScope();
    2406                         return ret;
    24071100                }
    24081101        } // anonymous namespace
Note: See TracChangeset for help on using the changeset viewer.