Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision bc1ab6197d06a7f4798c88e06e6fd49a90baa72c)
+++ src/GenPoly/Box.cc	(revision 8a3467770a0171ca9f928918daee8eb73663ff9a)
@@ -216,5 +216,4 @@
 		/// * Moves polymorphic returns in function types to pointer-type parameters
 		/// * adds type size and assertion parameters to parameter lists
-		/// * does dynamic calculation of type layouts
 		class Pass2 : public PolyMutator {
 		  public:
@@ -227,23 +226,9 @@
 			virtual Type *mutate( PointerType *pointerType );
 			virtual Type *mutate( FunctionType *funcType );
-			virtual Expression *mutate( SizeofExpr *sizeofExpr );
-			virtual Expression *mutate( AlignofExpr *alignofExpr );
-			virtual Expression *mutate( OffsetofExpr *offsetofExpr );
-			virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
-
-			virtual void doBeginScope();
-			virtual void doEndScope();
+			
 		  private:
 			void addAdapters( FunctionType *functionType );
-			/// Makes a new variable in the current scope with the given name, type & optional initializer
-			ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
-			/// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
-			bool findGeneric( Type *ty );
-			/// adds type parameters to the layout call; will generate the appropriate parameters if needed
-			void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
 
 			std::map< UniqueId, std::string > adapterName;
-			ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
-			ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
 		};
 
@@ -276,8 +261,10 @@
 		};
 
-		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
-		/// also fixes offsetof expressions.
-		class MemberExprFixer : public PolyMutator {
-		  public:
+		/// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
+		/// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
+		/// * Calculates polymorphic offsetof expressions from offset array
+		/// * Inserts dynamic calculation of polymorphic type layouts where needed
+		class PolyGenericCalculator : public PolyMutator {
+		public:
 			template< typename DeclClass >
 			DeclClass *handleDecl( DeclClass *decl, Type *type );
@@ -290,5 +277,22 @@
 			virtual Type *mutate( FunctionType *funcType );
 			virtual Expression *mutate( MemberExpr *memberExpr );
+			virtual Expression *mutate( SizeofExpr *sizeofExpr );
+			virtual Expression *mutate( AlignofExpr *alignofExpr );
 			virtual Expression *mutate( OffsetofExpr *offsetofExpr );
+			virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
+
+			virtual void doBeginScope();
+			virtual void doEndScope();
+
+		private:
+			/// Makes a new variable in the current scope with the given name, type & optional initializer
+			ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
+			/// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
+			bool findGeneric( Type *ty );
+			/// adds type parameters to the layout call; will generate the appropriate parameters if needed
+			void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
+			
+			ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
+			ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
 		};
 
@@ -340,5 +344,5 @@
 		Pass2 pass2;
 		GenericInstantiator instantiator;
-		MemberExprFixer memberFixer;
+		PolyGenericCalculator polyCalculator;
 		Pass3 pass3;
 		
@@ -347,5 +351,5 @@
 		mutateTranslationUnit/*All*/( translationUnit, pass2 );
 		instantiator.mutateDeclarationList( translationUnit );
-		mutateTranslationUnit/*All*/( translationUnit, memberFixer );
+		mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
 		mutateTranslationUnit/*All*/( translationUnit, pass3 );
 	}
@@ -1617,5 +1621,4 @@
 
 					seenTypes.insert( sizeName );
-					knownLayouts.insert( sizeName );  // make sure that any type information passed into the function is accounted for
 				}
 			}
@@ -1629,189 +1632,4 @@
 			scopeTyVars = oldtyVars;
 			return funcType;
-		}
-
-		ObjectDecl *Pass2::makeVar( const std::string &name, Type *type, Initializer *init ) {
-			ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
-			stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
-			return newObj;
-		}
-
-		void Pass2::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
-			for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
-				if ( findGeneric( *param ) ) {
-					// push size/align vars for a generic parameter back
-					layoutCall->get_args().push_back( new NameExpr( sizeofName( *param ) ) );
-					layoutCall->get_args().push_back( new NameExpr( alignofName( *param ) ) );
-				} else {
-					layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
-					layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
-				}
-			}
-		}
-
-		/// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
-		bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
-			bool hasDynamicLayout = false;
-
-			std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
-			std::list< Expression* >::const_iterator typeParam = typeParams.begin();
-			for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
-				// skip non-otype parameters
-				if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
-				TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
-				assert( typeExpr && "all otype parameters should be type expressions" );
-
-				Type *type = typeExpr->get_type();
-				out.push_back( type );
-				if ( isPolyType( type ) ) hasDynamicLayout = true;
-			}
-			assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
-
-			return hasDynamicLayout;
-		}
-		
-		bool Pass2::findGeneric( Type *ty ) {
-			if ( dynamic_cast< TypeInstType* >( ty ) ) {
-				// NOTE this assumes that all type variables will be properly bound, and thus have their layouts in scope
-				return true;
-			} else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
-				// check if this type already has a layout generated for it
-				std::string sizeName = sizeofName( ty );
-				if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
-				
-				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
-				std::list< Type* > otypeParams;
-				if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
-
-				// insert local variables for layout and generate call to layout function
-				knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
-				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-				int n_members = structTy->get_baseStruct()->get_members().size();
-				if ( n_members == 0 ) {
-					// all empty structs have the same layout - size 1, align 1
-					makeVar( sizeName, layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
-					makeVar( alignofName( ty ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
-					// NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
-				} else {
-					ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
-					ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
-					ObjectDecl *offsetVar = makeVar( offsetofName( ty ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
-
-					// generate call to layout function
-					UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + structTy->get_baseStruct()->get_name() ) );
-					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
-					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
-					layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
-					addOtypeParamsToLayoutCall( layoutCall, otypeParams );
-
-					stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
-				}
-				
-				return true;
-			} else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
-				// check if this type already has a layout generated for it
-				std::string sizeName = sizeofName( ty );
-				if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
-				
-				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
-				std::list< Type* > otypeParams;
-				if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
-
-				// insert local variables for layout and generate call to layout function
-				knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
-				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-				ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
-				ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
-				
-				// generate call to layout function
-				UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + unionTy->get_baseUnion()->get_name() ) );
-				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
-				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
-				addOtypeParamsToLayoutCall( layoutCall, otypeParams );
-
-				stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
-
-				return true;
-			}
-			
-			return false;
-		}
-		
-		Expression *Pass2::mutate( SizeofExpr *sizeofExpr ) {
-			Type *ty = sizeofExpr->get_type();
-			if ( findGeneric( ty ) ) {
-				Expression *ret = new NameExpr( sizeofName( ty ) );
-				delete sizeofExpr;
-				return ret;
-			}
-			return sizeofExpr;
-		}
-
-		Expression *Pass2::mutate( AlignofExpr *alignofExpr ) {
-			Type *ty = alignofExpr->get_type();
-			if ( findGeneric( ty ) ) {
-				Expression *ret = new NameExpr( alignofName( ty ) );
-				delete alignofExpr;
-				return ret;
-			}
-			return alignofExpr;
-		}
-
-		Expression *Pass2::mutate( OffsetofExpr *offsetofExpr ) {
-			findGeneric( offsetofExpr->get_type() );
-			return offsetofExpr;
-		}
-
-		Expression *Pass2::mutate( OffsetPackExpr *offsetPackExpr ) {
-			StructInstType *ty = offsetPackExpr->get_type();
-
-			Expression *ret = 0;
-			if ( findGeneric( ty ) ) {
-				// pull offset back from generated type information
-				ret = new NameExpr( offsetofName( ty ) );
-			} else {
-				std::string offsetName = offsetofName( ty );
-				if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
-					// use the already-generated offsets for this type
-					ret = new NameExpr( offsetName );
-				} else {
-					knownOffsets.insert( offsetName );
-					
-					std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
-					Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-					// build initializer list for offset array
-					std::list< Initializer* > inits;
-					for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
-						DeclarationWithType *memberDecl;
-						if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
-							memberDecl = origMember->clone();
-						} else {
-							memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
-						}
-						inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
-					}
-
-					// build the offset array and replace the pack with a reference to it
-					ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
-							new ListInit( inits ) );
-					ret = new VariableExpr( offsetArray );
-				}
-			}
-
-			delete offsetPackExpr;
-			return ret;
-		}
-
-		void Pass2::doBeginScope() {
-			knownLayouts.beginScope();
-			knownOffsets.beginScope();
-		}
-		
-		void Pass2::doEndScope() {
-			knownLayouts.endScope();
-			knownOffsets.beginScope();
 		}
 
@@ -2008,5 +1826,5 @@
 
 		template< typename DeclClass >
-		DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
+		DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
 			TyVarMap oldtyVars = scopeTyVars;
 			makeTyVarMap( type, scopeTyVars );
@@ -2018,22 +1836,22 @@
 		}
 
-		ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
+		ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
 			return handleDecl( objectDecl, objectDecl->get_type() );
 		}
 
-		DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
+		DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
 			return handleDecl( functionDecl, functionDecl->get_functionType() );
 		}
 
-		TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
+		TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
 			return handleDecl( typedefDecl, typedefDecl->get_base() );
 		}
 
-		TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
+		TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
 			scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
 			return Mutator::mutate( typeDecl );
 		}
 
-		Type * MemberExprFixer::mutate( PointerType *pointerType ) {
+		Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
 			TyVarMap oldtyVars = scopeTyVars;
 			makeTyVarMap( pointerType, scopeTyVars );
@@ -2045,9 +1863,18 @@
 		}
 
-		Type * MemberExprFixer::mutate( FunctionType *functionType ) {
+		Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
 			TyVarMap oldtyVars = scopeTyVars;
-			makeTyVarMap( functionType, scopeTyVars );
-
-			Type *ret = Mutator::mutate( functionType );
+			makeTyVarMap( funcType, scopeTyVars );
+
+			// make sure that any type information passed into the function is accounted for
+			for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
+				// condition here duplicates that in Pass2::mutate( FunctionType* )
+				Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
+				if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
+					knownLayouts.insert( sizeofName( polyBase ) );
+				}
+			}
+			
+			Type *ret = Mutator::mutate( funcType );
 
 			scopeTyVars = oldtyVars;
@@ -2055,7 +1882,7 @@
 		}
 
-		Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
+		Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
 			if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
-				if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
+				if ( findGeneric( objectDecl->get_type() ) ) {
 					// change initialization of a polymorphic value object
 					// to allocate storage with alloca
@@ -2109,5 +1936,5 @@
 		}
 		
-		Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
+		Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
 			// mutate, exiting early if no longer MemberExpr
 			Expression *expr = Mutator::mutate( memberExpr );
@@ -2126,4 +1953,5 @@
 			Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
 			if ( ! objectType ) return memberExpr;
+			findGeneric( objectType ); // ensure layout for this type is available
 
 			Expression *newMemberExpr = 0;
@@ -2157,5 +1985,143 @@
 		}
 
-		Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
+		ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
+			ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
+			stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
+			return newObj;
+		}
+
+		void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
+			for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
+				if ( findGeneric( *param ) ) {
+					// push size/align vars for a generic parameter back
+					layoutCall->get_args().push_back( new NameExpr( sizeofName( *param ) ) );
+					layoutCall->get_args().push_back( new NameExpr( alignofName( *param ) ) );
+				} else {
+					layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
+					layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
+				}
+			}
+		}
+
+		/// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
+		bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
+			bool hasDynamicLayout = false;
+
+			std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
+			std::list< Expression* >::const_iterator typeParam = typeParams.begin();
+			for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
+				// skip non-otype parameters
+				if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
+				TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
+				assert( typeExpr && "all otype parameters should be type expressions" );
+
+				Type *type = typeExpr->get_type();
+				out.push_back( type );
+				if ( isPolyType( type ) ) hasDynamicLayout = true;
+			}
+			assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
+
+			return hasDynamicLayout;
+		}
+
+		bool PolyGenericCalculator::findGeneric( Type *ty ) {
+			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
+				// duplicate logic from isPolyType()
+				if ( env ) {
+					if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
+						return findGeneric( newType );
+					} // if
+				} // if
+				if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
+					// NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
+					return true;
+				}
+				return false;
+			} else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
+				// check if this type already has a layout generated for it
+				std::string sizeName = sizeofName( ty );
+				if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
+
+				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
+				std::list< Type* > otypeParams;
+				if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
+
+				// insert local variables for layout and generate call to layout function
+				knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
+				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+
+				int n_members = structTy->get_baseStruct()->get_members().size();
+				if ( n_members == 0 ) {
+					// all empty structs have the same layout - size 1, align 1
+					makeVar( sizeName, layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
+					makeVar( alignofName( ty ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
+					// NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
+				} else {
+					ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
+					ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
+					ObjectDecl *offsetVar = makeVar( offsetofName( ty ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
+
+					// generate call to layout function
+					UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + structTy->get_baseStruct()->get_name() ) );
+					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
+					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
+					layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
+					addOtypeParamsToLayoutCall( layoutCall, otypeParams );
+
+					stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
+				}
+
+				return true;
+			} else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
+				// check if this type already has a layout generated for it
+				std::string sizeName = sizeofName( ty );
+				if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
+
+				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
+				std::list< Type* > otypeParams;
+				if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
+
+				// insert local variables for layout and generate call to layout function
+				knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
+				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+
+				ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
+				ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
+
+				// generate call to layout function
+				UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + unionTy->get_baseUnion()->get_name() ) );
+				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
+				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
+				addOtypeParamsToLayoutCall( layoutCall, otypeParams );
+
+				stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
+
+				return true;
+			}
+
+			return false;
+		}
+
+		Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
+			Type *ty = sizeofExpr->get_type();
+			if ( findGeneric( ty ) ) {
+				Expression *ret = new NameExpr( sizeofName( ty ) );
+				delete sizeofExpr;
+				return ret;
+			}
+			return sizeofExpr;
+		}
+
+		Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
+			Type *ty = alignofExpr->get_type();
+			if ( findGeneric( ty ) ) {
+				Expression *ret = new NameExpr( alignofName( ty ) );
+				delete alignofExpr;
+				return ret;
+			}
+			return alignofExpr;
+		}
+
+		Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
 			// mutate, exiting early if no longer OffsetofExpr
 			Expression *expr = Mutator::mutate( offsetofExpr );
@@ -2164,7 +2130,7 @@
 
 			// only mutate expressions for polymorphic structs/unions
-			Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
-			if ( ! ty ) return offsetofExpr;
-
+			Type *ty = offsetofExpr->get_type();
+			if ( ! findGeneric( ty ) ) return offsetofExpr;
+			
 			if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
 				// replace offsetof expression by index into offset array
@@ -2182,4 +2148,55 @@
 		}
 
+		Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
+			StructInstType *ty = offsetPackExpr->get_type();
+
+			Expression *ret = 0;
+			if ( findGeneric( ty ) ) {
+				// pull offset back from generated type information
+				ret = new NameExpr( offsetofName( ty ) );
+			} else {
+				std::string offsetName = offsetofName( ty );
+				if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
+					// use the already-generated offsets for this type
+					ret = new NameExpr( offsetName );
+				} else {
+					knownOffsets.insert( offsetName );
+
+					std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
+					Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+
+					// build initializer list for offset array
+					std::list< Initializer* > inits;
+					for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
+						DeclarationWithType *memberDecl;
+						if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
+							memberDecl = origMember->clone();
+						} else {
+							memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
+						}
+						inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
+					}
+
+					// build the offset array and replace the pack with a reference to it
+					ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
+							new ListInit( inits ) );
+					ret = new VariableExpr( offsetArray );
+				}
+			}
+
+			delete offsetPackExpr;
+			return ret;
+		}
+
+		void PolyGenericCalculator::doBeginScope() {
+			knownLayouts.beginScope();
+			knownOffsets.beginScope();
+		}
+
+		void PolyGenericCalculator::doEndScope() {
+			knownLayouts.endScope();
+			knownOffsets.beginScope();
+		}
+
 ////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
 
