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

Merge branch 'master' into gc_noraii

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rc5833e8 r0f9e4403  
    1414//
    1515
     16#include <algorithm>
     17#include <iterator>
     18#include <list>
     19#include <map>
    1620#include <set>
    1721#include <stack>
    1822#include <string>
    19 #include <iterator>
    20 #include <algorithm>
     23#include <utility>
     24#include <vector>
    2125#include <cassert>
    2226
    2327#include "Box.h"
    24 #include "InstantiateGeneric.h"
     28#include "DeclMutator.h"
    2529#include "PolyMutator.h"
    2630#include "FindFunction.h"
     31#include "ScopedMap.h"
     32#include "ScopedSet.h"
    2733#include "ScrubTyVars.h"
    2834
     
    3036
    3137#include "SynTree/Constant.h"
    32 #include "SynTree/Type.h"
     38#include "SynTree/Declaration.h"
    3339#include "SynTree/Expression.h"
    3440#include "SynTree/Initializer.h"
     41#include "SynTree/Mutator.h"
    3542#include "SynTree/Statement.h"
    36 #include "SynTree/Mutator.h"
     43#include "SynTree/Type.h"
     44#include "SynTree/TypeSubstitution.h"
    3745
    3846#include "ResolvExpr/TypeEnvironment.h"
     
    4048#include "ResolvExpr/typeops.h"
    4149
     50#include "SymTab/Indexer.h"
    4251#include "SymTab/Mangler.h"
    4352
     
    5463                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
    5564
     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               
    56163                /// 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
    57164                class Pass1 : public PolyMutator {
     
    72179                        virtual void doEndScope();
    73180                  private:
    74                         /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
    75                         Expression *makeOffsetArray( StructInstType *type );
    76181                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
    77182                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
     
    100205                        ObjectDecl *makeTemporary( Type *type );
    101206
    102                         typedef std::map< std::string, DeclarationWithType *> AdapterMap;
    103                         std::map< std::string, DeclarationWithType *> assignOps;
    104                         ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
    105                         std::stack< AdapterMap > adapters;
     207                        ScopedMap< std::string, DeclarationWithType *> assignOps;    ///< Currently known type variable assignment operators
     208                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
     209                        ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
     210                       
    106211                        DeclarationWithType *retval;
    107212                        bool useRetval;
     
    109214                };
    110215
    111                 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well
     216                /// * Moves polymorphic returns in function types to pointer-type parameters
     217                /// * adds type size and assertion parameters to parameter lists
    112218                class Pass2 : public PolyMutator {
    113219                  public:
     
    120226                        virtual Type *mutate( PointerType *pointerType );
    121227                        virtual Type *mutate( FunctionType *funcType );
     228                       
    122229                  private:
    123230                        void addAdapters( FunctionType *functionType );
     
    126233                };
    127234
    128                 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
    129                 /// also fixes offsetof expressions.
    130                 class MemberExprFixer : public PolyMutator {
    131                   public:
     235                /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     236                class GenericInstantiator : public DeclMutator {
     237                        /// Map of (generic type, parameter list) pairs to concrete type instantiations
     238                        InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
     239                        /// Namer for concrete types
     240                        UniqueName typeNamer;
     241
     242                public:
     243                        GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
     244
     245                        virtual Type* mutate( StructInstType *inst );
     246                        virtual Type* mutate( UnionInstType *inst );
     247
     248        //              virtual Expression* mutate( MemberExpr *memberExpr );
     249
     250                        virtual void doBeginScope();
     251                        virtual void doEndScope();
     252                private:
     253                        /// Wrap instantiation lookup for structs
     254                        StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
     255                        /// Wrap instantiation lookup for unions
     256                        UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
     257                        /// Wrap instantiation insertion for structs
     258                        void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
     259                        /// Wrap instantiation insertion for unions
     260                        void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
     261                };
     262
     263                /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
     264                /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
     265                /// * Calculates polymorphic offsetof expressions from offset array
     266                /// * Inserts dynamic calculation of polymorphic type layouts where needed
     267                class PolyGenericCalculator : public PolyMutator {
     268                public:
    132269                        template< typename DeclClass >
    133270                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    140277                        virtual Type *mutate( FunctionType *funcType );
    141278                        virtual Expression *mutate( MemberExpr *memberExpr );
     279                        virtual Expression *mutate( SizeofExpr *sizeofExpr );
     280                        virtual Expression *mutate( AlignofExpr *alignofExpr );
    142281                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
     282                        virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
     283
     284                        virtual void doBeginScope();
     285                        virtual void doEndScope();
     286
     287                private:
     288                        /// Makes a new variable in the current scope with the given name, type & optional initializer
     289                        ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
     290                        /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
     291                        bool findGeneric( Type *ty );
     292                        /// adds type parameters to the layout call; will generate the appropriate parameters if needed
     293                        void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
     294
     295                        /// Enters a new scope for type-variables, adding the type variables from ty
     296                        void beginTypeScope( Type *ty );
     297                        /// Exits the type-variable scope
     298                        void endTypeScope();
     299                       
     300                        ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
     301                        ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
    143302                };
    144303
     
    159318        } // anonymous namespace
    160319
    161         void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {
    162                 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    163                         if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {
    164                                 (*i)->print( os );
    165                                 os << std::endl;
    166                         } // if
    167                 } // for
    168         }
    169 
    170320        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
    171321        template< typename MutatorType >
     
    195345
    196346        void box( std::list< Declaration *>& translationUnit ) {
     347                LayoutFunctionBuilder layoutBuilder;
    197348                Pass1 pass1;
    198349                Pass2 pass2;
    199                 MemberExprFixer memberFixer;
     350                GenericInstantiator instantiator;
     351                PolyGenericCalculator polyCalculator;
    200352                Pass3 pass3;
     353               
     354                layoutBuilder.mutateDeclarationList( translationUnit );
    201355                mutateTranslationUnit/*All*/( translationUnit, pass1 );
    202356                mutateTranslationUnit/*All*/( translationUnit, pass2 );
    203                 instantiateGeneric( translationUnit );
    204                 mutateTranslationUnit/*All*/( translationUnit, memberFixer );
     357                instantiator.mutateDeclarationList( translationUnit );
     358                mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
    205359                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    206360        }
    207361
     362        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     363
     364        DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
     365                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     366                mutateAll( functionDecl->get_oldDecls(), *this );
     367                ++functionNesting;
     368                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     369                --functionNesting;
     370                return functionDecl;
     371        }
     372       
     373        /// Get a list of type declarations that will affect a layout function
     374        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
     375                std::list< TypeDecl * > otypeDecls;
     376
     377                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     378                        if ( (*decl)->get_kind() == TypeDecl::Any ) {
     379                                otypeDecls.push_back( *decl );
     380                        }
     381                }
     382               
     383                return otypeDecls;
     384        }
     385
     386        /// Adds parameters for otype layout to a function type
     387        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
     388                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     389               
     390                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     391                        TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
     392                        std::string paramName = mangleType( &paramType );
     393                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     394                        layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     395                }
     396        }
     397
     398        /// Builds a layout function declaration
     399        FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {
     400                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     401                // because each unit generates copies of the default routines for each aggregate.
     402                FunctionDecl *layoutDecl = new FunctionDecl(
     403                        layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
     404                layoutDecl->fixUniqueId();
     405                return layoutDecl;
     406        }
     407
     408        /// Makes a unary operation
     409        Expression *makeOp( const std::string &name, Expression *arg ) {
     410                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     411                expr->get_args().push_back( arg );
     412                return expr;
     413        }
     414
     415        /// Makes a binary operation
     416        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
     417                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     418                expr->get_args().push_back( lhs );
     419                expr->get_args().push_back( rhs );
     420                return expr;
     421        }
     422
     423        /// Returns the dereference of a local pointer variable
     424        Expression *derefVar( ObjectDecl *var ) {
     425                return makeOp( "*?", new VariableExpr( var ) );
     426        }
     427
     428        /// makes an if-statement with a single-expression if-block and no then block
     429        Statement *makeCond( Expression *cond, Expression *ifPart ) {
     430                return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
     431        }
     432
     433        /// makes a statement that assigns rhs to lhs if lhs < rhs
     434        Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
     435                return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
     436        }
     437
     438        /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
     439        Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
     440                // check that the lhs is zeroed out to the level of rhs
     441                Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
     442                // if not aligned, increment to alignment
     443                Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
     444                return makeCond( ifCond, ifExpr );
     445        }
     446       
     447        /// adds an expression to a compound statement
     448        void addExpr( CompoundStmt *stmts, Expression *expr ) {
     449                stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
     450        }
     451
     452        /// adds a statement to a compound statement
     453        void addStmt( CompoundStmt *stmts, Statement *stmt ) {
     454                stmts->get_kids().push_back( stmt );
     455        }
     456       
     457        Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
     458                // do not generate layout function for "empty" tag structs
     459                if ( structDecl->get_members().empty() ) return structDecl;
     460
     461                // get parameters that can change layout, exiting early if none
     462                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
     463                if ( otypeParams.empty() ) return structDecl;
     464
     465                // build layout function signature
     466                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     467                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     468                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     469               
     470                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     471                layoutFnType->get_parameters().push_back( sizeParam );
     472                ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     473                layoutFnType->get_parameters().push_back( alignParam );
     474                ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     475                layoutFnType->get_parameters().push_back( offsetParam );
     476                addOtypeParams( layoutFnType, otypeParams );
     477
     478                // build function decl
     479                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );
     480
     481                // calculate struct layout in function body
     482
     483                // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
     484                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
     485                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     486                unsigned long n_members = 0;
     487                bool firstMember = true;
     488                for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
     489                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     490                        assert( dwt );
     491                        Type *memberType = dwt->get_type();
     492
     493                        if ( firstMember ) {
     494                                firstMember = false;
     495                        } else {
     496                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
     497                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
     498                        }
     499                       
     500                        // place current size in the current offset index
     501                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
     502                                                                              derefVar( sizeParam ) ) );
     503                        ++n_members;
     504
     505                        // add member size to current size
     506                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     507                       
     508                        // take max of member alignment and global alignment
     509                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     510                }
     511                // make sure the type is end-padded to a multiple of its alignment
     512                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     513
     514                addDeclarationAfter( layoutDecl );
     515                return structDecl;
     516        }
     517       
     518        Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
     519                // do not generate layout function for "empty" tag unions
     520                if ( unionDecl->get_members().empty() ) return unionDecl;
     521               
     522                // get parameters that can change layout, exiting early if none
     523                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
     524                if ( otypeParams.empty() ) return unionDecl;
     525
     526                // build layout function signature
     527                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     528                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     529                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     530               
     531                ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     532                layoutFnType->get_parameters().push_back( sizeParam );
     533                ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     534                layoutFnType->get_parameters().push_back( alignParam );
     535                addOtypeParams( layoutFnType, otypeParams );
     536
     537                // build function decl
     538                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );
     539
     540                // calculate union layout in function body
     541                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     542                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     543                for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
     544                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     545                        assert( dwt );
     546                        Type *memberType = dwt->get_type();
     547                       
     548                        // take max member size and global size
     549                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     550                       
     551                        // take max of member alignment and global alignment
     552                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     553                }
     554                // make sure the type is end-padded to a multiple of its alignment
     555                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     556
     557                addDeclarationAfter( layoutDecl );
     558                return unionDecl;
     559        }
     560       
    208561        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    209562
     
    245598                }
    246599
    247                 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {
    248                         adapters.push(AdapterMap());
    249                 }
     600                Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
    250601
    251602                /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     
    309660
    310661                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    311                         // if this is a polymorphic assignment function, put it in the map for this scope
     662                        // if this is a assignment function, put it in the map for this scope
    312663                        if ( Type *assignedType = isAssignment( functionDecl ) ) {
    313664                                if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
     
    318669                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    319670                                doBeginScope();
    320                                 TyVarMap oldtyVars = scopeTyVars;
    321                                 std::map< std::string, DeclarationWithType *> oldassignOps = assignOps;
     671                                scopeTyVars.beginScope();
     672                                assignOps.beginScope();
    322673                                DeclarationWithType *oldRetval = retval;
    323674                                bool oldUseRetval = useRetval;
     
    350701                                } // for
    351702
    352                                 AdapterMap & adapters = Pass1::adapters.top();
    353703                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    354704                                        std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     
    361711                                functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
    362712
    363                                 scopeTyVars = oldtyVars;
    364                                 assignOps = oldassignOps;
    365                                 // std::cerr << "end FunctionDecl: ";
    366                                 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    367                                 //      std::cerr << i->first << " ";
    368                                 // }
    369                                 // std::cerr << "\n";
     713                                scopeTyVars.endScope();
     714                                assignOps.endScope();
    370715                                retval = oldRetval;
    371716                                useRetval = oldUseRetval;
     
    400745                }
    401746
    402                 Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
    403                         std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
    404 
    405                         // make a new temporary array
    406                         Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    407                         std::stringstream lenGen;
    408                         lenGen << baseMembers.size();
    409                         ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );
    410                         ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );
    411 
    412                         // build initializer list for temporary
    413                         std::list< Initializer* > inits;
    414                         for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
    415                                 DeclarationWithType *memberDecl;
    416                                 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
    417                                         memberDecl = origMember->clone();
    418                                 } else {
    419                                         memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
    420                                 }
    421                                 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
    422                         }
    423                         arrayTemp->set_init( new ListInit( inits ) );
    424 
    425                         // return variable pointing to temporary
    426                         return new VariableExpr( arrayTemp );
    427                 }
    428 
    429747                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
    430                         Type *polyBase = hasPolyBase( parmType, exprTyVars );
    431                         if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    432                                 std::string sizeName = sizeofName( polyBase );
    433                                 if ( seenTypes.count( sizeName ) ) return;
     748                        Type *polyType = isPolyType( parmType, exprTyVars );
     749                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     750                                std::string typeName = mangleType( polyType );
     751                                if ( seenTypes.count( typeName ) ) return;
    434752
    435753                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
     
    437755                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
    438756                                arg++;
    439                                 if ( dynamic_cast< StructInstType* >( polyBase ) ) {
     757                                if ( dynamic_cast< StructInstType* >( polyType ) ) {
    440758                                        if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
    441                                                 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
    442                                                 arg++;
     759                                                // zero-length arrays are forbidden by C, so don't pass offset for empty struct
     760                                                if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
     761                                                        arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
     762                                                        arg++;
     763                                                }
    443764                                        } else {
    444765                                                throw SemanticError( "Cannot pass non-struct type for generic struct" );
     
    446767                                }
    447768
    448                                 seenTypes.insert( sizeName );
     769                                seenTypes.insert( typeName );
    449770                        }
    450771                }
     
    588909                                        return;
    589910                                } else if ( arg->get_results().front()->get_isLvalue() ) {
    590                                         // VariableExpr and MemberExpr are lvalues
    591                                         arg = new AddressExpr( arg );
     911                                        // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
     912                                        if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
     913                                                commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
     914                                        } else {
     915                                                arg = new AddressExpr( arg );
     916                                        }
    592917                                } else {
    593918                                        // use type computed in unification to declare boxed variables
     
    6841009                        } // for
    6851010                }
    686 
    687 
    6881011
    6891012                FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     
    7721095                                        mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
    7731096
    774                                         AdapterMap & adapters = Pass1::adapters.top();
    775                                         AdapterMap::iterator adapter = adapters.find( mangleName );
     1097                                        typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     1098                                        AdapterIter adapter = adapters.find( mangleName );
    7761099                                        if ( adapter == adapters.end() ) {
    7771100                                                // adapter has not been created yet in the current scope, so define it
    7781101                                                FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
    779                                                 adapter = adapters.insert( adapters.begin(), std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     1102                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     1103                                                adapter = answer.first;
    7801104                                                stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
    7811105                                        } // if
     
    8011125                                addAssign->get_args().push_back( appExpr->get_args().front() );
    8021126                        } // if
    803                         addAssign->get_args().push_back( new NameExpr( sizeofName( polyType ) ) );
     1127                        addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
    8041128                        addAssign->get_results().front() = appExpr->get_results().front()->clone();
    8051129                        if ( appExpr->get_env() ) {
     
    8281152                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    8291153                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    830                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1154                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    8311155                                                        ret->get_args().push_back( appExpr->get_args().front() );
    8321156                                                        ret->get_args().push_back( multiply );
     
    8341158                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    8351159                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    836                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
     1160                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    8371161                                                        ret->get_args().push_back( multiply );
    8381162                                                        ret->get_args().push_back( appExpr->get_args().back() );
     
    8971221                                                        UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
    8981222                                                        divide->get_args().push_back( appExpr );
    899                                                         divide->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1223                                                        divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    9001224                                                        divide->get_results().push_front( appExpr->get_results().front()->clone() );
    9011225                                                        if ( appExpr->get_env() ) {
     
    9071231                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    9081232                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    909                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
     1233                                                        multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
    9101234                                                        appExpr->get_args().back() = multiply;
    9111235                                                } else if ( baseType2 ) {
    9121236                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    9131237                                                        multiply->get_args().push_back( appExpr->get_args().front() );
    914                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
     1238                                                        multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
    9151239                                                        appExpr->get_args().front() = multiply;
    9161240                                                } // if
     
    9221246                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
    9231247                                                        multiply->get_args().push_back( appExpr->get_args().back() );
    924                                                         multiply->get_args().push_back( new NameExpr( sizeofName( baseType ) ) );
     1248                                                        multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
    9251249                                                        appExpr->get_args().back() = multiply;
    9261250                                                } // if
     
    9591283                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    9601284
    961                         TyVarMap exprTyVars;
     1285                        TyVarMap exprTyVars( (TypeDecl::Kind)-1 );
    9621286                        makeTyVarMap( function, exprTyVars );
    9631287                        ReferenceToType *polyRetType = isPolyRet( function );
     
    9821306
    9831307                        boxParams( appExpr, function, arg, exprTyVars );
    984 
    9851308                        passAdapters( appExpr, function, exprTyVars );
    9861309
     
    10621385                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
    10631386                                        // find assignment operator for type variable
    1064                                         std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
     1387                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    10651388                                        if ( assignIter == assignOps.end() ) {
    10661389                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
     
    10841407                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
    10851408                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
    1086                                                 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
    1087 
    1088                                                 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
    1089                                                 assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
    1090                                                 DeclarationWithType *actualDecl = asserts.front();
    1091                                                 TypeInstType *actualType = isTypeInstAssignment( actualDecl );
    1092                                                 assert( actualType && "First assertion of type with assertions should be assignment operator" );
     1409                                                // Add appropriate mapping to assignment expression environment
    10931410                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
    10941411                                                assert( formalTypeExpr && "type parameters must be type expressions" );
    10951412                                                Type *formalType = formalTypeExpr->get_type();
    1096                                                 assignExpr->get_env()->add( actualType->get_name(), formalType );
    1097                                                
     1413                                                assignExpr->get_env()->add( (*forallIt)->get_name(), formalType );
     1414
     1415                                                // skip types with no assign op (ftype/dtype)
     1416                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue;
     1417
     1418                                                // find assignment operator for formal type
    10981419                                                DeclarationWithType *assertAssign = 0;
    10991420                                                if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
    1100                                                         std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
     1421                                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
    11011422                                                        if ( assertAssignIt == assignOps.end() ) {
    11021423                                                                throw SemanticError( "No assignment operation found for ", formalTypeInstType );
     
    11091430                                                        }
    11101431                                                }
    1111                                                
    1112 
     1432
     1433                                                // add inferred parameter for field assignment operator to assignment expression
     1434                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
     1435                                                assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
     1436                                                DeclarationWithType *actualDecl = asserts.front();
    11131437                                                assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
    11141438                                                        = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
     
    11361460
    11371461                Type * Pass1::mutate( PointerType *pointerType ) {
    1138                         TyVarMap oldtyVars = scopeTyVars;
     1462                        scopeTyVars.beginScope();
    11391463                        makeTyVarMap( pointerType, scopeTyVars );
    11401464
    11411465                        Type *ret = Mutator::mutate( pointerType );
    11421466
    1143                         scopeTyVars = oldtyVars;
     1467                        scopeTyVars.endScope();
    11441468                        return ret;
    11451469                }
    11461470
    11471471                Type * Pass1::mutate( FunctionType *functionType ) {
    1148                         TyVarMap oldtyVars = scopeTyVars;
     1472                        scopeTyVars.beginScope();
    11491473                        makeTyVarMap( functionType, scopeTyVars );
    11501474
    11511475                        Type *ret = Mutator::mutate( functionType );
    11521476
    1153                         scopeTyVars = oldtyVars;
     1477                        scopeTyVars.endScope();
    11541478                        return ret;
    11551479                }
    11561480
    11571481                void Pass1::doBeginScope() {
    1158                         // push a copy of the current map
    1159                         adapters.push(adapters.top());
     1482                        adapters.beginScope();
    11601483                        scopedAssignOps.beginScope();
    11611484                }
    11621485
    11631486                void Pass1::doEndScope() {
    1164                         adapters.pop();
     1487                        adapters.endScope();
    11651488                        scopedAssignOps.endScope();
    11661489                }
     
    12171540
    12181541                Type * Pass2::mutate( PointerType *pointerType ) {
    1219                         TyVarMap oldtyVars = scopeTyVars;
     1542                        scopeTyVars.beginScope();
    12201543                        makeTyVarMap( pointerType, scopeTyVars );
    12211544
    12221545                        Type *ret = Mutator::mutate( pointerType );
    12231546
    1224                         scopeTyVars = oldtyVars;
     1547                        scopeTyVars.endScope();
    12251548                        return ret;
    12261549                }
    12271550
    12281551                Type *Pass2::mutate( FunctionType *funcType ) {
    1229                         TyVarMap oldtyVars = scopeTyVars;
     1552                        scopeTyVars.beginScope();
    12301553                        makeTyVarMap( funcType, scopeTyVars );
    12311554
     
    12441567                        ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
    12451568                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
    1246 //   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
    12471569                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
    12481570                                ObjectDecl *sizeParm, *alignParm;
     
    12501572                                if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
    12511573                                        TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
     1574                                        std::string parmName = mangleType( &parmType );
    12521575
    12531576                                        sizeParm = newObj.clone();
    1254                                         sizeParm->set_name( sizeofName( &parmType ) );
     1577                                        sizeParm->set_name( sizeofName( parmName ) );
    12551578                                        last = funcType->get_parameters().insert( last, sizeParm );
    12561579                                        ++last;
    12571580
    12581581                                        alignParm = newObj.clone();
    1259                                         alignParm->set_name( alignofName( &parmType ) );
     1582                                        alignParm->set_name( alignofName( parmName ) );
    12601583                                        last = funcType->get_parameters().insert( last, alignParm );
    12611584                                        ++last;
     
    12721595                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    12731596                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
    1274                                 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
    1275                                 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    1276                                         std::string sizeName = sizeofName( polyBase );
    1277                                         if ( seenTypes.count( sizeName ) ) continue;
     1597                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1598                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     1599                                        std::string typeName = mangleType( polyType );
     1600                                        if ( seenTypes.count( typeName ) ) continue;
    12781601
    12791602                                        ObjectDecl *sizeParm, *alignParm, *offsetParm;
    12801603                                        sizeParm = newObj.clone();
    1281                                         sizeParm->set_name( sizeName );
     1604                                        sizeParm->set_name( sizeofName( typeName ) );
    12821605                                        last = funcType->get_parameters().insert( last, sizeParm );
    12831606                                        ++last;
    12841607
    12851608                                        alignParm = newObj.clone();
    1286                                         alignParm->set_name( alignofName( polyBase ) );
     1609                                        alignParm->set_name( alignofName( typeName ) );
    12871610                                        last = funcType->get_parameters().insert( last, alignParm );
    12881611                                        ++last;
    12891612
    1290                                         if ( dynamic_cast< StructInstType* >( polyBase ) ) {
    1291                                                 offsetParm = newPtr.clone();
    1292                                                 offsetParm->set_name( offsetofName( polyBase ) );
    1293                                                 last = funcType->get_parameters().insert( last, offsetParm );
    1294                                                 ++last;
     1613                                        if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
     1614                                                // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
     1615                                                if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
     1616                                                        offsetParm = newPtr.clone();
     1617                                                        offsetParm->set_name( offsetofName( typeName ) );
     1618                                                        last = funcType->get_parameters().insert( last, offsetParm );
     1619                                                        ++last;
     1620                                                }
    12951621                                        }
    12961622
    1297                                         seenTypes.insert( sizeName );
     1623                                        seenTypes.insert( typeName );
    12981624                                }
    12991625                        }
     
    13051631                        mutateAll( funcType->get_parameters(), *this );
    13061632
    1307                         scopeTyVars = oldtyVars;
     1633                        scopeTyVars.endScope();
    13081634                        return funcType;
    13091635                }
    13101636
    1311 ////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
     1637//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
     1638
     1639                /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
     1640                bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
     1641                        bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
     1642
     1643                        // substitute concrete types for given parameters, and incomplete types for placeholders
     1644                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     1645                        std::list< Expression* >::const_iterator param = params.begin();
     1646                        for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
     1647        //                      switch ( (*baseParam)->get_kind() ) {
     1648        //                      case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
     1649                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     1650                                        assert(paramType && "Aggregate parameters should be type expressions");
     1651                                        out.push_back( paramType->clone() );
     1652                                        // check that the substituted type isn't a type variable itself
     1653                                        if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
     1654                                                allConcrete = false;
     1655                                        }
     1656        //                              break;
     1657        //                      }
     1658        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1659        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1660        //                              break;
     1661        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1662        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1663        //                              break;
     1664        //                      }
     1665                        }
     1666
     1667                        // if any parameters left over, not done
     1668                        if ( baseParam != baseParams.end() ) return false;
     1669        //              // if not enough parameters given, substitute remaining incomplete types for placeholders
     1670        //              for ( ; baseParam != baseParams.end(); ++baseParam ) {
     1671        //                      switch ( (*baseParam)->get_kind() ) {
     1672        //                      case TypeDecl::Any:    // no more substitutions here, fail early
     1673        //                              return false;
     1674        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1675        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1676        //                              break;
     1677        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1678        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1679        //                              break;
     1680        //                      }
     1681        //              }
     1682
     1683                        return allConcrete;
     1684                }
     1685
     1686                /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
     1687                void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
     1688                                                                std::list< Declaration* >& out ) {
     1689                        // substitute types into new members
     1690                        TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     1691                        for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
     1692                                Declaration *newMember = (*member)->clone();
     1693                                subs.apply(newMember);
     1694                                out.push_back( newMember );
     1695                        }
     1696                }
     1697
     1698                Type* GenericInstantiator::mutate( StructInstType *inst ) {
     1699                        // mutate subtypes
     1700                        Type *mutated = Mutator::mutate( inst );
     1701                        inst = dynamic_cast< StructInstType* >( mutated );
     1702                        if ( ! inst ) return mutated;
     1703
     1704                        // exit early if no need for further mutation
     1705                        if ( inst->get_parameters().empty() ) return inst;
     1706                        assert( inst->get_baseParameters() && "Base struct has parameters" );
     1707
     1708                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1709                        std::list< TypeExpr* > typeSubs;
     1710                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1711                                deleteAll( typeSubs );
     1712                                return inst;
     1713                        }
     1714
     1715                        // make concrete instantiation of generic type
     1716                        StructDecl *concDecl = lookup( inst, typeSubs );
     1717                        if ( ! concDecl ) {
     1718                                // set concDecl to new type, insert type declaration into statements to add
     1719                                concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
     1720                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
     1721                                DeclMutator::addDeclaration( concDecl );
     1722                                insert( inst, typeSubs, concDecl );
     1723                        }
     1724                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
     1725                        newInst->set_baseStruct( concDecl );
     1726
     1727                        deleteAll( typeSubs );
     1728                        delete inst;
     1729                        return newInst;
     1730                }
     1731
     1732                Type* GenericInstantiator::mutate( UnionInstType *inst ) {
     1733                        // mutate subtypes
     1734                        Type *mutated = Mutator::mutate( inst );
     1735                        inst = dynamic_cast< UnionInstType* >( mutated );
     1736                        if ( ! inst ) return mutated;
     1737
     1738                        // exit early if no need for further mutation
     1739                        if ( inst->get_parameters().empty() ) return inst;
     1740                        assert( inst->get_baseParameters() && "Base union has parameters" );
     1741
     1742                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1743                        std::list< TypeExpr* > typeSubs;
     1744                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1745                                deleteAll( typeSubs );
     1746                                return inst;
     1747                        }
     1748
     1749                        // make concrete instantiation of generic type
     1750                        UnionDecl *concDecl = lookup( inst, typeSubs );
     1751                        if ( ! concDecl ) {
     1752                                // set concDecl to new type, insert type declaration into statements to add
     1753                                concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
     1754                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
     1755                                DeclMutator::addDeclaration( concDecl );
     1756                                insert( inst, typeSubs, concDecl );
     1757                        }
     1758                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
     1759                        newInst->set_baseUnion( concDecl );
     1760
     1761                        deleteAll( typeSubs );
     1762                        delete inst;
     1763                        return newInst;
     1764                }
     1765
     1766        //      /// Gets the base struct or union declaration for a member expression; NULL if not applicable
     1767        //      AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
     1768        //              // get variable for member aggregate
     1769        //              VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
     1770        //              if ( ! varExpr ) return NULL;
     1771        //
     1772        //              // get object for variable
     1773        //              ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
     1774        //              if ( ! objectDecl ) return NULL;
     1775        //
     1776        //              // get base declaration from object type
     1777        //              Type *objectType = objectDecl->get_type();
     1778        //              StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
     1779        //              if ( structType ) return structType->get_baseStruct();
     1780        //              UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
     1781        //              if ( unionType ) return unionType->get_baseUnion();
     1782        //
     1783        //              return NULL;
     1784        //      }
     1785        //
     1786        //      /// Finds the declaration with the given name, returning decls.end() if none such
     1787        //      std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
     1788        //              for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     1789        //                      if ( (*decl)->get_name() == name ) return decl;
     1790        //              }
     1791        //              return decls.end();
     1792        //      }
     1793        //
     1794        //      Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
     1795        //              // mutate, exiting early if no longer MemberExpr
     1796        //              Expression *expr = Mutator::mutate( memberExpr );
     1797        //              memberExpr = dynamic_cast< MemberExpr* >( expr );
     1798        //              if ( ! memberExpr ) return expr;
     1799        //
     1800        //              // get declaration of member and base declaration of member, exiting early if not found
     1801        //              AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
     1802        //              if ( ! memberBase ) return memberExpr;
     1803        //              DeclarationWithType *memberDecl = memberExpr->get_member();
     1804        //              std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
     1805        //              if ( baseIt == memberBase->get_members().end() ) return memberExpr;
     1806        //              DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
     1807        //              if ( ! baseDecl ) return memberExpr;
     1808        //
     1809        //              // check if stated type of the member is not the type of the member's declaration; if so, need a cast
     1810        //              // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
     1811        //              SymTab::Indexer dummy;
     1812        //              if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
     1813        //              else return new CastExpr( memberExpr, memberDecl->get_type() );
     1814        //      }
     1815
     1816                void GenericInstantiator::doBeginScope() {
     1817                        DeclMutator::doBeginScope();
     1818                        instantiations.beginScope();
     1819                }
     1820
     1821                void GenericInstantiator::doEndScope() {
     1822                        DeclMutator::doEndScope();
     1823                        instantiations.endScope();
     1824                }
     1825
     1826////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
     1827
     1828                void PolyGenericCalculator::beginTypeScope( Type *ty ) {
     1829                        scopeTyVars.beginScope();
     1830                        makeTyVarMap( ty, scopeTyVars );
     1831                }
     1832
     1833                void PolyGenericCalculator::endTypeScope() {
     1834                        scopeTyVars.endScope();
     1835                }
    13121836
    13131837                template< typename DeclClass >
    1314                 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
    1315                         TyVarMap oldtyVars = scopeTyVars;
    1316                         makeTyVarMap( type, scopeTyVars );
     1838                DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
     1839                        beginTypeScope( type );
     1840                        knownLayouts.beginScope();
     1841                        knownOffsets.beginScope();
    13171842
    13181843                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    13191844
    1320                         scopeTyVars = oldtyVars;
     1845                        knownOffsets.endScope();
     1846                        knownLayouts.endScope();
     1847                        endTypeScope();
    13211848                        return ret;
    13221849                }
    13231850
    1324                 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
     1851                ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
    13251852                        return handleDecl( objectDecl, objectDecl->get_type() );
    13261853                }
    13271854
    1328                 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
     1855                DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
    13291856                        return handleDecl( functionDecl, functionDecl->get_functionType() );
    13301857                }
    13311858
    1332                 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
     1859                TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
    13331860                        return handleDecl( typedefDecl, typedefDecl->get_base() );
    13341861                }
    13351862
    1336                 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
     1863                TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
    13371864                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    13381865                        return Mutator::mutate( typeDecl );
    13391866                }
    13401867
    1341                 Type * MemberExprFixer::mutate( PointerType *pointerType ) {
    1342                         TyVarMap oldtyVars = scopeTyVars;
    1343                         makeTyVarMap( pointerType, scopeTyVars );
     1868                Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
     1869                        beginTypeScope( pointerType );
    13441870
    13451871                        Type *ret = Mutator::mutate( pointerType );
    13461872
    1347                         scopeTyVars = oldtyVars;
     1873                        endTypeScope();
    13481874                        return ret;
    13491875                }
    13501876
    1351                 Type * MemberExprFixer::mutate( FunctionType *functionType ) {
    1352                         TyVarMap oldtyVars = scopeTyVars;
    1353                         makeTyVarMap( functionType, scopeTyVars );
    1354 
    1355                         Type *ret = Mutator::mutate( functionType );
    1356 
    1357                         scopeTyVars = oldtyVars;
     1877                Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
     1878                        beginTypeScope( funcType );
     1879
     1880                        // make sure that any type information passed into the function is accounted for
     1881                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
     1882                                // condition here duplicates that in Pass2::mutate( FunctionType* )
     1883                                Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1884                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     1885                                        knownLayouts.insert( mangleType( polyType ) );
     1886                                }
     1887                        }
     1888                       
     1889                        Type *ret = Mutator::mutate( funcType );
     1890
     1891                        endTypeScope();
    13581892                        return ret;
    13591893                }
    13601894
    1361                 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
     1895                Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
    13621896                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    1363                                 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
     1897                                if ( findGeneric( objectDecl->get_type() ) ) {
    13641898                                        // change initialization of a polymorphic value object
    13651899                                        // to allocate storage with alloca
    13661900                                        Type *declType = objectDecl->get_type();
    13671901                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
    1368                                         alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
     1902                                        alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) );
    13691903
    13701904                                        delete objectDecl->get_init();
     
    13981932                        ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
    13991933                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
    1400                         fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
     1934                        fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
    14011935                        fieldOffset->get_args().push_back( fieldIndex );
    14021936                        return fieldOffset;
     
    14131947                }
    14141948               
    1415                 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
     1949                Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
    14161950                        // mutate, exiting early if no longer MemberExpr
    14171951                        Expression *expr = Mutator::mutate( memberExpr );
     
    14301964                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
    14311965                        if ( ! objectType ) return memberExpr;
     1966                        findGeneric( objectType ); // ensure layout for this type is available
    14321967
    14331968                        Expression *newMemberExpr = 0;
     
    14611996                }
    14621997
    1463                 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
     1998                ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
     1999                        ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
     2000                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     2001                        return newObj;
     2002                }
     2003
     2004                void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
     2005                        for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     2006                                if ( findGeneric( *param ) ) {
     2007                                        // push size/align vars for a generic parameter back
     2008                                        std::string paramName = mangleType( *param );
     2009                                        layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
     2010                                        layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
     2011                                } else {
     2012                                        layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
     2013                                        layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
     2014                                }
     2015                        }
     2016                }
     2017
     2018                /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
     2019                bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
     2020                        bool hasDynamicLayout = false;
     2021
     2022                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     2023                        std::list< Expression* >::const_iterator typeParam = typeParams.begin();
     2024                        for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
     2025                                // skip non-otype parameters
     2026                                if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
     2027                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
     2028                                assert( typeExpr && "all otype parameters should be type expressions" );
     2029
     2030                                Type *type = typeExpr->get_type();
     2031                                out.push_back( type );
     2032                                if ( isPolyType( type ) ) hasDynamicLayout = true;
     2033                        }
     2034                        assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
     2035
     2036                        return hasDynamicLayout;
     2037                }
     2038
     2039                bool PolyGenericCalculator::findGeneric( Type *ty ) {
     2040                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
     2041                                // duplicate logic from isPolyType()
     2042                                if ( env ) {
     2043                                        if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
     2044                                                return findGeneric( newType );
     2045                                        } // if
     2046                                } // if
     2047                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     2048                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
     2049                                        return true;
     2050                                }
     2051                                return false;
     2052                        } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
     2053                                // check if this type already has a layout generated for it
     2054                                std::string typeName = mangleType( ty );
     2055                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2056
     2057                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2058                                std::list< Type* > otypeParams;
     2059                                if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
     2060
     2061                                // insert local variables for layout and generate call to layout function
     2062                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2063                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2064
     2065                                int n_members = structTy->get_baseStruct()->get_members().size();
     2066                                if ( n_members == 0 ) {
     2067                                        // all empty structs have the same layout - size 1, align 1
     2068                                        makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2069                                        makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2070                                        // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
     2071                                } else {
     2072                                        ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2073                                        ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2074                                        ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
     2075
     2076                                        // generate call to layout function
     2077                                        UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
     2078                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2079                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2080                                        layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
     2081                                        addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2082
     2083                                        stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2084                                }
     2085
     2086                                return true;
     2087                        } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
     2088                                // check if this type already has a layout generated for it
     2089                                std::string typeName = mangleType( ty );
     2090                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     2091
     2092                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2093                                std::list< Type* > otypeParams;
     2094                                if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
     2095
     2096                                // insert local variables for layout and generate call to layout function
     2097                                knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2098                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2099
     2100                                ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
     2101                                ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
     2102
     2103                                // generate call to layout function
     2104                                UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
     2105                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2106                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2107                                addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2108
     2109                                stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2110
     2111                                return true;
     2112                        }
     2113
     2114                        return false;
     2115                }
     2116
     2117                Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
     2118                        Type *ty = sizeofExpr->get_type();
     2119                        if ( findGeneric( ty ) ) {
     2120                                Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) );
     2121                                delete sizeofExpr;
     2122                                return ret;
     2123                        }
     2124                        return sizeofExpr;
     2125                }
     2126
     2127                Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
     2128                        Type *ty = alignofExpr->get_type();
     2129                        if ( findGeneric( ty ) ) {
     2130                                Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
     2131                                delete alignofExpr;
     2132                                return ret;
     2133                        }
     2134                        return alignofExpr;
     2135                }
     2136
     2137                Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
    14642138                        // mutate, exiting early if no longer OffsetofExpr
    14652139                        Expression *expr = Mutator::mutate( offsetofExpr );
     
    14682142
    14692143                        // only mutate expressions for polymorphic structs/unions
    1470                         Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
    1471                         if ( ! ty ) return offsetofExpr;
    1472 
     2144                        Type *ty = offsetofExpr->get_type();
     2145                        if ( ! findGeneric( ty ) ) return offsetofExpr;
     2146                       
    14732147                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
    14742148                                // replace offsetof expression by index into offset array
     
    14862160                }
    14872161
     2162                Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
     2163                        StructInstType *ty = offsetPackExpr->get_type();
     2164
     2165                        Expression *ret = 0;
     2166                        if ( findGeneric( ty ) ) {
     2167                                // pull offset back from generated type information
     2168                                ret = new NameExpr( offsetofName( mangleType( ty ) ) );
     2169                        } else {
     2170                                std::string offsetName = offsetofName( mangleType( ty ) );
     2171                                if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     2172                                        // use the already-generated offsets for this type
     2173                                        ret = new NameExpr( offsetName );
     2174                                } else {
     2175                                        knownOffsets.insert( offsetName );
     2176
     2177                                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
     2178                                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2179
     2180                                        // build initializer list for offset array
     2181                                        std::list< Initializer* > inits;
     2182                                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
     2183                                                DeclarationWithType *memberDecl;
     2184                                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
     2185                                                        memberDecl = origMember->clone();
     2186                                                } else {
     2187                                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
     2188                                                }
     2189                                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
     2190                                        }
     2191
     2192                                        // build the offset array and replace the pack with a reference to it
     2193                                        ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
     2194                                                        new ListInit( inits ) );
     2195                                        ret = new VariableExpr( offsetArray );
     2196                                }
     2197                        }
     2198
     2199                        delete offsetPackExpr;
     2200                        return ret;
     2201                }
     2202
     2203                void PolyGenericCalculator::doBeginScope() {
     2204                        knownLayouts.beginScope();
     2205                        knownOffsets.beginScope();
     2206                }
     2207
     2208                void PolyGenericCalculator::doEndScope() {
     2209                        knownLayouts.endScope();
     2210                        knownOffsets.endScope();
     2211                }
     2212
    14882213////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    14892214
    14902215                template< typename DeclClass >
    14912216                DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
    1492                         TyVarMap oldtyVars = scopeTyVars;
     2217                        scopeTyVars.beginScope();
    14932218                        makeTyVarMap( type, scopeTyVars );
    14942219
     
    14962221                        ScrubTyVars::scrub( decl, scopeTyVars );
    14972222
    1498                         scopeTyVars = oldtyVars;
     2223                        scopeTyVars.endScope();
    14992224                        return ret;
    15002225                }
     
    15262251
    15272252                Type * Pass3::mutate( PointerType *pointerType ) {
    1528                         TyVarMap oldtyVars = scopeTyVars;
     2253                        scopeTyVars.beginScope();
    15292254                        makeTyVarMap( pointerType, scopeTyVars );
    15302255
    15312256                        Type *ret = Mutator::mutate( pointerType );
    15322257
    1533                         scopeTyVars = oldtyVars;
     2258                        scopeTyVars.endScope();
    15342259                        return ret;
    15352260                }
    15362261
    15372262                Type * Pass3::mutate( FunctionType *functionType ) {
    1538                         TyVarMap oldtyVars = scopeTyVars;
     2263                        scopeTyVars.beginScope();
    15392264                        makeTyVarMap( functionType, scopeTyVars );
    15402265
    15412266                        Type *ret = Mutator::mutate( functionType );
    15422267
    1543                         scopeTyVars = oldtyVars;
     2268                        scopeTyVars.endScope();
    15442269                        return ret;
    15452270                }
Note: See TracChangeset for help on using the changeset viewer.