Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/GenPoly/Box.cc	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -306,4 +306,5 @@
 
 		void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
+			// pass size/align for type variables
 			for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
 				ResolvExpr::EqvClass eqvClass;
@@ -321,4 +322,30 @@
 				} // if
 			} // for
+
+			// add size/align for generic types to parameter list
+			//assert( ! appExpr->get_function()->get_results().empty() );
+			if ( appExpr->get_function()->get_results().empty() ) return;
+			FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
+			assert( funcType );
+			
+			std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
+			std::list< Expression* >::const_iterator fnArg = arg;
+			std::set< std::string > seenTypes; //< names for generic types we've seen
+			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
+				Type *parmType = (*fnParm)->get_type();
+				if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, exprTyVars ) ) {
+					std::string sizeName = sizeofName( parmType );
+					if ( seenTypes.count( sizeName ) ) continue;
+
+					assert( ! (*fnArg)->get_results().empty() );
+					Type *argType = (*fnArg)->get_results().front();
+					arg = appExpr->get_args().insert( arg, new SizeofExpr( argType->clone() ) );
+					arg++;
+					arg = appExpr->get_args().insert( arg, new AlignofExpr( argType->clone() ) );
+					arg++;
+
+					seenTypes.insert( sizeName );
+				}
+			}
 		}
 
@@ -971,5 +998,6 @@
 			TyVarMap oldtyVars = scopeTyVars;
 			makeTyVarMap( funcType, scopeTyVars );
-  
+
+			// move polymorphic return type to parameter list
 			std::string typeName;
 			if ( isPolyRet( funcType, typeName ) ) {
@@ -979,5 +1007,6 @@
 				funcType->get_returnVals().pop_front();
 			}
-  
+
+			// add size/align and assertions for type parameters to parameter list
 			std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
 			std::list< DeclarationWithType *> inferredParams;
@@ -1007,4 +1036,29 @@
 				(*tyParm)->get_assertions().clear();
 			}
+
+			// add size/align for generic types to parameter list
+			std::set< std::string > seenTypes; //< sizeofName for generic types we've seen
+			for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
+				Type *parmType = (*fnParm)->get_type();
+				if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, scopeTyVars ) ) {
+					std::string sizeName = sizeofName( parmType );
+					if ( seenTypes.count( sizeName ) ) continue;
+					
+					ObjectDecl *sizeParm, *alignParm;
+					sizeParm = newObj.clone();
+					sizeParm->set_name( sizeName );
+					last = funcType->get_parameters().insert( last, sizeParm );
+					++last;
+
+					alignParm = newObj.clone();
+					alignParm->set_name( alignofName( parmType ) );
+					last = funcType->get_parameters().insert( last, alignParm );
+					++last;
+
+					seenTypes.insert( sizeName );
+				}
+			}
+
+			// splice assertion parameters into parameter list
 			funcType->get_parameters().splice( last, inferredParams );
 			addAdapters( funcType );
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/GenPoly/GenPoly.cc	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -68,5 +68,15 @@
 
 	namespace {
-		/// Checks a parameter list for polymorphic parameters
+		/// Checks a parameter list for polymorphic parameters; will substitute according to env if present
+		bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
+			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
+				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
+				assert(paramType && "Aggregate parameters should be type expressions");
+				if ( isPolyType( paramType->get_type(), env ) ) return true;
+			}
+			return false;
+		}
+
+		/// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
 		bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
 			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
@@ -78,4 +88,20 @@
 		}
 	}
+
+	Type *isPolyType( Type *type, const TypeSubstitution *env ) {
+		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
+			if ( env ) {
+				if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
+					return isPolyType( newType, env );
+				} // if
+			} // if
+			return type;
+		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
+			if ( hasPolyParams( structType->get_parameters(), env ) ) return type;
+		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
+			if ( hasPolyParams( unionType->get_parameters(), env ) ) return type;
+		}
+		return 0;
+	}
 	
 	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
@@ -84,9 +110,9 @@
 				if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
 					return isPolyType( newType, tyVars, env );
+				} // if
 			} // if
-		} // if
 			if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
 				return type;
-	}
+			}
 		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
 			if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type;
@@ -97,4 +123,17 @@
 	}
 
+	Type *isPolyPtr( Type *type, const TypeSubstitution *env ) {
+		if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
+			return isPolyType( ptr->get_base(), env );
+		} else if ( env ) {
+			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
+				if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
+					return isPolyPtr( newType, env );
+				} // if
+			} // if
+		} // if
+		return 0;
+	}
+	
 	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
 		if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
@@ -110,4 +149,13 @@
 	}
 
+	FunctionType * getFunctionType( Type *ty ) {
+		PointerType *ptrType;
+		if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
+			return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
+		} else {
+			return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
+		}
+	}
+
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
 		for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
@@ -118,9 +166,9 @@
 
 	std::string sizeofName( Type *ty ) {
-		return std::string( "_sizeof_" ) + SymTab::Mangler::mangle( ty, false, false );
+		return std::string( "_sizeof_" ) + SymTab::Mangler::mangleType( ty );
 	}
 
 	std::string alignofName( Type *ty ) {
-		return std::string( "_alignof_" ) + SymTab::Mangler::mangle( ty, false, false );
+		return std::string( "_alignof_" ) + SymTab::Mangler::mangleType( ty );
 	}
 } // namespace GenPoly
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/GenPoly/GenPoly.h	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -37,8 +37,17 @@
 
 	/// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
+	Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
+	
+	/// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
 	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
 
 	/// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided
+	Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );
+	
+	/// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
 	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
+
+	/// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
+	FunctionType * getFunctionType( Type *ty );
 
 	/// Prints type variable map
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/GenPoly/ScrubTyVars.cc	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -46,6 +46,6 @@
 	Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) {
 		// sizeof( T ) => _sizeof_T parameter, which is the size of T
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( szeof->get_type() ) ) {
-			Expression *expr = new NameExpr( sizeofName( typeInst ) );
+		if ( Type *polyType = isPolyType( szeof->get_type() ) ) {
+			Expression *expr = new NameExpr( sizeofName( polyType ) );
 			return expr;
 		} else {
@@ -56,6 +56,6 @@
 	Expression * ScrubTyVars::mutate( AlignofExpr *algnof ) {
 		// alignof( T ) => _alignof_T parameter, which is the alignment of T
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( algnof->get_type() ) ) {
-			Expression *expr = new NameExpr( alignofName( typeInst ) );
+		if ( Type *polyType = isPolyType( algnof->get_type() ) ) {
+			Expression *expr = new NameExpr( alignofName( polyType ) );
 			return expr;
 		} else {
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/GenPoly/Specialize.cc	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -17,4 +17,5 @@
 
 #include "Specialize.h"
+#include "GenPoly.h"
 #include "PolyMutator.h"
 
@@ -87,14 +88,4 @@
 	}
 
-	/// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
-	FunctionType * getFunctionType( Type *ty ) {
-		PointerType *ptrType;
-		if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
-			return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
-		} else {
-			return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
-		}
-	}
-
 	/// Generates a thunk that calls `actual` with type `funType` and returns its address
 	Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/SymTab/Mangler.cc	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -30,6 +30,12 @@
 
 namespace SymTab {
-	Mangler::Mangler( bool mangleOverridable, bool includeQualifiers )
-		: nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), includeQualifiers(includeQualifiers) {}
+	std::string Mangler::mangleType( Type *ty ) {
+		Mangler mangler( false, true );
+		maybeAccept( ty, mangler );
+		return mangler.get_mangleName();
+	}
+	
+	Mangler::Mangler( bool mangleOverridable, bool typeMode )
+		: nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ) {}
 		
 	Mangler::Mangler( const Mangler &rhs ) : mangleName() {
@@ -38,5 +44,5 @@
 		isTopLevel = rhs.isTopLevel;
 		mangleOverridable = rhs.mangleOverridable;
-		includeQualifiers = rhs.includeQualifiers;
+		typeMode = rhs.typeMode;
 	}
 
@@ -149,13 +155,39 @@
 	void Mangler::mangleRef( ReferenceToType *refType, std::string prefix ) {
 		printQualifiers( refType );
+
 		mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name();
 	}
 
+	void Mangler::mangleGenericRef( ReferenceToType *refType, std::string prefix ) {
+		printQualifiers( refType );
+
+		std::ostringstream oldName( mangleName.str() );
+		mangleName.clear();
+
+		mangleName << prefix << refType->get_name();
+
+		std::list< Expression* >& params = refType->get_parameters();
+		if ( ! params.empty() ) {
+			mangleName << "_";
+			for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
+				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
+				assert(paramType && "Aggregate parameters should be type expressions");
+				maybeAccept( paramType->get_type(), *this );
+			}
+			mangleName << "_";
+		}
+
+		oldName << mangleName.str().length() << mangleName.str();
+		mangleName.str( oldName.str() );
+	}
+
 	void Mangler::visit( StructInstType *aggregateUseType ) {
-		mangleRef( aggregateUseType, "s" );
+		if ( typeMode ) mangleGenericRef( aggregateUseType, "s" );
+		else mangleRef( aggregateUseType, "s" );
 	}
 
 	void Mangler::visit( UnionInstType *aggregateUseType ) {
-		mangleRef( aggregateUseType, "u" );
+		if ( typeMode ) mangleGenericRef( aggregateUseType, "u" );
+		else mangleRef( aggregateUseType, "u" );
 	}
 
@@ -207,5 +239,5 @@
 	void Mangler::printQualifiers( Type *type ) {
 		// skip if not including qualifiers
-		if ( ! includeQualifiers ) return;
+		if ( typeMode ) return;
 		
 		if ( ! type->get_forall().empty() ) {
@@ -227,5 +259,5 @@
 				varNums[ (*i )->get_name() ] = std::pair< int, int >( nextVarNum++, (int )(*i )->get_kind() );
 				for ( std::list< DeclarationWithType* >::iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
-					Mangler sub_mangler( mangleOverridable, includeQualifiers );
+					Mangler sub_mangler( mangleOverridable, typeMode );
 					sub_mangler.nextVarNum = nextVarNum;
 					sub_mangler.isTopLevel = false;
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision faf8857316238fb243bc16493862a605ed9b5e6e)
+++ src/SymTab/Mangler.h	(revision c23f80716c2e7a2b40be4dd756671294ce694bfa)
@@ -25,6 +25,9 @@
 	class Mangler : public Visitor {
 	  public:
+		/// Mangle syntax tree object; primary interface to clients
 		template< typename SynTreeClass >
-	    static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true, bool includeQualifiers = true ); // interface to clients
+	    static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true );
+		/// Mangle a type name; secondary interface
+		static std::string mangleType( Type* ty );
 
 		virtual void visit( ObjectDecl *declaration );
@@ -51,11 +54,12 @@
 		bool isTopLevel;                ///< Is the Mangler at the top level
 		bool mangleOverridable;         ///< Specially mangle overridable built-in methods
-		bool includeQualifiers;         ///< Include type qualifiers in mangled name
+		bool typeMode;                  ///< Produce a unique mangled name for a type
   
-		Mangler( bool mangleOverridable, bool includeQualifiers );
+		Mangler( bool mangleOverridable, bool typeMode );
 		Mangler( const Mangler & );
   
 		void mangleDecl( DeclarationWithType *declaration );
 		void mangleRef( ReferenceToType *refType, std::string prefix );
+		void mangleGenericRef( ReferenceToType *refType, std::string prefix );
   
 		void printQualifiers( Type *type );
@@ -63,6 +67,6 @@
 
 	template< typename SynTreeClass >
-	std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable, bool includeQualifiers ) {
-		Mangler mangler( mangleOverridable, includeQualifiers );
+	std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable ) {
+		Mangler mangler( mangleOverridable, false );
 		maybeAccept( decl, mangler );
 		return mangler.get_mangleName();
