Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/CodeGen/CodeGenerator.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CodeGenerator.cc --
+// CodeGenerator.cc -- 
 //
 // Author           : Richard C. Bilson
@@ -98,5 +98,5 @@
 		handleStorageClass( objectDecl );
 		output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
-
+	
 		if ( objectDecl->get_init() ) {
 			output << " = ";
@@ -112,5 +112,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-
+	
 		std::list< Declaration * > &memb = aggDecl->get_members();
 
@@ -118,12 +118,12 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize;
+			cur_indent += CodeGenerator::tabsize; 
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
-				output << indent;
+				output << indent; 
 				(*i)->accept( *this );
 				output << ";" << endl;
 			}
 
-			cur_indent -= CodeGenerator::tabsize;
+			cur_indent -= CodeGenerator::tabsize; 
 
 			output << indent << "}";
@@ -140,5 +140,5 @@
 		handleAggregate( aggregateDecl );
 	}
-
+  
 	void CodeGenerator::visit( EnumDecl *aggDecl ) {
 		output << "enum ";
@@ -146,5 +146,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-
+	
 		std::list< Declaration* > &memb = aggDecl->get_members();
 
@@ -152,9 +152,9 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize;
+			cur_indent += CodeGenerator::tabsize; 
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
 				ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i );
 				assert( obj );
-				output << indent << mangleName( obj );
+				output << indent << mangleName( obj ); 
 				if ( obj->get_init() ) {
 					output << " = ";
@@ -164,17 +164,17 @@
 			} // for
 
-			cur_indent -= CodeGenerator::tabsize;
+			cur_indent -= CodeGenerator::tabsize; 
 
 			output << indent << "}";
 		} // if
 	}
-
+  
 	void CodeGenerator::visit( ContextDecl *aggregateDecl ) {}
-
+  
 	void CodeGenerator::visit( TypedefDecl *typeDecl ) {
 		output << "typedef ";
 		output << genType( typeDecl->get_base(), typeDecl->get_name() );
 	}
-
+  
 	void CodeGenerator::visit( TypeDecl *typeDecl ) {
 		// really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes,
@@ -216,5 +216,5 @@
 	}
 
-	void CodeGenerator::visit( Constant *constant ) {
+	void CodeGenerator::visit( Constant *constant ) { 
 		output << constant->get_value() ;
 	}
@@ -233,5 +233,5 @@
 						assert( arg != applicationExpr->get_args().end() );
 						if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
-
+	        
 							*arg = addrExpr->get_arg();
 						} else {
@@ -242,10 +242,10 @@
 						break;
 					}
-
+	      
 				  default:
 					// do nothing
 					;
 				}
-
+	    
 				switch ( opInfo.type ) {
 				  case OT_INDEX:
@@ -256,10 +256,10 @@
 					output << "]";
 					break;
-
+	      
 				  case OT_CALL:
 					// there are no intrinsic definitions of the function call operator
 					assert( false );
 					break;
-
+	      
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -270,5 +270,5 @@
 					output << ")";
 					break;
-
+	      
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -287,5 +287,5 @@
 					output << ")";
 					break;
-
+	      
 				  case OT_CONSTANT:
 				  case OT_LABELADDRESS:
@@ -306,5 +306,5 @@
 		} // if
 	}
-
+  
 	void CodeGenerator::visit( UntypedExpr *untypedExpr ) {
 		if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
@@ -320,9 +320,9 @@
 					output << "]";
 					break;
-
+	      
 				  case OT_CALL:
 					assert( false );
 					break;
-
+	      
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -334,5 +334,5 @@
 					output << ")";
 					break;
-
+	      
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -341,5 +341,5 @@
 					output << opInfo.symbol;
 					break;
-
+  
 				  case OT_INFIX:
 				  case OT_INFIXASSIGN:
@@ -351,5 +351,5 @@
 					output << ")";
 					break;
-
+					
 				  case OT_CONSTANT:
 					// there are no intrinsic definitions of 0 or 1 as functions
@@ -369,5 +369,5 @@
 		} // if
 	}
-
+  
 	void CodeGenerator::visit( NameExpr *nameExpr ) {
 		OperatorInfo opInfo;
@@ -379,5 +379,5 @@
 		} // if
 	}
-
+  
 	void CodeGenerator::visit( AddressExpr *addressExpr ) {
 		output << "(&";
@@ -408,14 +408,14 @@
 		output << ")";
 	}
-
+  
 	void CodeGenerator::visit( UntypedMemberExpr *memberExpr ) {
 		assert( false );
 	}
-
+  
 	void CodeGenerator::visit( MemberExpr *memberExpr ) {
 		memberExpr->get_aggregate()->accept( *this );
 		output << "." << mangleName( memberExpr->get_member() );
 	}
-
+  
 	void CodeGenerator::visit( VariableExpr *variableExpr ) {
 		OperatorInfo opInfo;
@@ -426,10 +426,10 @@
 		} // if
 	}
-
+  
 	void CodeGenerator::visit( ConstantExpr *constantExpr ) {
 		assert( constantExpr->get_constant() );
 		constantExpr->get_constant()->accept( *this );
 	}
-
+  
 	void CodeGenerator::visit( SizeofExpr *sizeofExpr ) {
 		output << "sizeof(";
@@ -442,15 +442,23 @@
 	}
 
-	void CodeGenerator::visit( AlignofExpr *sizeofExpr ) {
+	void CodeGenerator::visit( AlignofExpr *alignofExpr ) {
 		// use GCC extension to avoid bumping std to C11
 		output << "__alignof__(";
-		if ( sizeofExpr->get_isType() ) {
-			output << genType( sizeofExpr->get_type(), "" );
-		} else {
-			sizeofExpr->get_expr()->accept( *this );
+		if ( alignofExpr->get_isType() ) {
+			output << genType( alignofExpr->get_type(), "" );
+		} else {
+			alignofExpr->get_expr()->accept( *this );
 		} // if
 		output << ")";
 	}
 
+	void CodeGenerator::visit( OffsetofExpr *offsetofExpr ) {
+		// use GCC builtin
+		output << "__builtin_offsetof(";
+		output << genType( offsetofExpr->get_type(), "" );
+		output << ", " << mangleName( offsetofExpr->get_member() );
+		output << ")";
+	}
+  
 	void CodeGenerator::visit( LogicalExpr *logicalExpr ) {
 		output << "(";
@@ -464,5 +472,5 @@
 		output << ")";
 	}
-
+  
 	void CodeGenerator::visit( ConditionalExpr *conditionalExpr ) {
 		output << "(";
@@ -474,5 +482,5 @@
 		output << ")";
 	}
-
+  
 	void CodeGenerator::visit( CommaExpr *commaExpr ) {
 		output << "(";
@@ -482,7 +490,7 @@
 		output << ")";
 	}
-
+  
 	void CodeGenerator::visit( TupleExpr *tupleExpr ) {}
-
+  
 	void CodeGenerator::visit( TypeExpr *typeExpr ) {}
 
@@ -515,5 +523,5 @@
 			}
 		}
-		cur_indent -= CodeGenerator::tabsize;
+		cur_indent -= CodeGenerator::tabsize; 
 
 		output << indent << "}";
@@ -521,6 +529,6 @@
 
 	void CodeGenerator::visit( ExprStmt *exprStmt ) {
-		// I don't see why this check is necessary.
-		// If this starts to cause problems then put it back in,
+		// I don't see why this check is necessary. 
+		// If this starts to cause problems then put it back in, 
 		// with an explanation
 		assert( exprStmt );
@@ -572,5 +580,5 @@
 		switchStmt->get_condition()->accept( *this );
 		output << " ) ";
-
+		
 		output << "{" << std::endl;
 		cur_indent += CodeGenerator::tabsize;
@@ -592,5 +600,5 @@
 		} // if
 		output << ":\n";
-
+		
 		std::list<Statement *> sts = caseStmt->get_statements();
 
@@ -609,5 +617,5 @@
 			if ( ! branchStmt->get_target().empty() )
 				output << "goto " << branchStmt->get_target();
-			else {
+			else { 
 				if ( branchStmt->get_computedTarget() != 0 ) {
 					output << "goto *";
@@ -660,6 +668,6 @@
 
 	void CodeGenerator::visit( ForStmt *forStmt ) {
-		// initialization is always hoisted, so don't
-		// bother doing anything with that
+		// initialization is always hoisted, so don't 
+		// bother doing anything with that 
 		output << "for (;";
 
@@ -685,5 +693,5 @@
 	void CodeGenerator::visit( DeclStmt *declStmt ) {
 		declStmt->get_decl()->accept( *this );
-
+	
 		if ( doSemicolon( declStmt->get_decl() ) ) {
 			output << ";";
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/CodeGen/CodeGenerator.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -61,4 +61,5 @@
 		virtual void visit( SizeofExpr *sizeofExpr );
 		virtual void visit( AlignofExpr *alignofExpr );
+		virtual void visit( OffsetofExpr *offsetofExpr );
 		virtual void visit( LogicalExpr *logicalExpr );
 		virtual void visit( ConditionalExpr *conditionalExpr );
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/Box.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -22,6 +22,8 @@
 
 #include "Box.h"
+#include "InstantiateGeneric.h"
 #include "PolyMutator.h"
 #include "FindFunction.h"
+#include "ScopedMap.h"
 #include "ScrubTyVars.h"
 
@@ -69,19 +71,33 @@
 			virtual void doEndScope();
 		  private:
+			/// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
+			Expression *makeOffsetArray( StructInstType *type );
+			/// passes extra type parameters into a polymorphic function application
 			void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
+			/// wraps a function application with a new temporary for the out-parameter return value
 			Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
-			Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg );
+			/// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
+			void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
+			/// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
+			/// If `doClone` is set to false, will not clone interior types
+			Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
+			/// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
+			Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
 			Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
 			void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
+			/// Stores assignment operators from assertion list in local map of assignment operations
 			void findAssignOps( const std::list< TypeDecl *> &forall );
 			void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
 			FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
+			/// Replaces intrinsic operator functions with their arithmetic desugaring
 			Expression *handleIntrinsics( ApplicationExpr *appExpr );
+			/// Inserts a new temporary variable into the current scope with an auto-generated name
 			ObjectDecl *makeTemporary( Type *type );
 
 			typedef std::map< std::string, DeclarationWithType *> AdapterMap;
 			std::map< std::string, DeclarationWithType *> assignOps;
+			ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
 			std::stack< AdapterMap > adapters;
 			DeclarationWithType *retval;
@@ -107,6 +123,6 @@
 		};
 
-		/// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
-		class Pass3 : public PolyMutator {
+		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
+		class MemberExprFixer : public PolyMutator {
 		  public:
 			template< typename DeclClass >
@@ -119,4 +135,18 @@
 			virtual Type *mutate( PointerType *pointerType );
 			virtual Type *mutate( FunctionType *funcType );
+			virtual Expression *mutate( MemberExpr *memberExpr );
+		};
+		
+		/// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
+		class Pass3 : public PolyMutator {
+		  public:
+			template< typename DeclClass >
+			DeclClass *handleDecl( DeclClass *decl, Type *type );
+			virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
+			virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
+			virtual TypedefDecl *mutate( TypedefDecl *objectDecl );
+			virtual TypeDecl *mutate( TypeDecl *objectDecl );
+			virtual Type *mutate( PointerType *pointerType );
+			virtual Type *mutate( FunctionType *funcType );
 		  private:
 		};
@@ -133,11 +163,40 @@
 	}
 
+	/// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
+	template< typename MutatorType >
+	inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
+		bool seenIntrinsic = false;
+		SemanticError errors;
+		for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
+			try {
+				if ( *i ) {
+					if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
+						seenIntrinsic = true;
+					} else if ( seenIntrinsic ) {
+						seenIntrinsic = false; // break on this line when debugging for end of prelude
+					}
+					
+					*i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
+					assert( *i );
+				} // if
+			} catch( SemanticError &e ) {
+				errors.append( e );
+			} // try
+		} // for
+		if ( ! errors.isEmpty() ) {
+			throw errors;
+		} // if
+	}
+
 	void box( std::list< Declaration *>& translationUnit ) {
 		Pass1 pass1;
 		Pass2 pass2;
+		MemberExprFixer memberFixer;
 		Pass3 pass3;
-		mutateAll( translationUnit, pass1 );
-		mutateAll( translationUnit, pass2 );
-		mutateAll( translationUnit, pass3 );
+		mutateTranslationUnit/*All*/( translationUnit, pass1 );
+		mutateTranslationUnit/*All*/( translationUnit, pass2 );
+		instantiateGeneric( translationUnit );
+		mutateTranslationUnit/*All*/( translationUnit, memberFixer );
+		mutateTranslationUnit/*All*/( translationUnit, pass3 );
 	}
 
@@ -185,17 +244,14 @@
 		}
 
-		// returns true if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be)
-		bool checkAssignment( DeclarationWithType *decl, std::string &name ) {
+		/// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise
+		ReferenceToType *isAssignment( DeclarationWithType *decl ) {
 			if ( decl->get_name() == "?=?" ) {
-				if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) {
-					if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) {
-						if ( funType->get_parameters().size() == 2 ) {
-							if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
-								if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
-									if ( TypeInstType *typeInst2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
-										if ( typeInst->get_name() == typeInst2->get_name() ) {
-											name = typeInst->get_name();
-											return true;
-										} // if
+				if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+					if ( funType->get_parameters().size() == 2 ) {
+						if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
+							if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) {
+								if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) {
+									if ( refType->get_name() == refType2->get_name() ) {
+										return refType;
 									} // if
 								} // if
@@ -205,5 +261,5 @@
 				} // if
 			} // if
-			return false;
+			return 0;
 		}
 
@@ -214,6 +270,6 @@
 				for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
 					std::string typeName;
-					if ( checkAssignment( *assert, typeName ) ) {
-						assignOps[ typeName ] = *assert;
+					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
+						assignOps[ typeInst->get_name() ] = *assert;
 					} // if
 				} // for
@@ -222,4 +278,11 @@
 
 		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
+			// if this is a polymorphic assignment function, put it in the map for this scope
+			if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( refType ) ) {
+					scopedAssignOps.insert( refType->get_name(), functionDecl );
+				}
+			}
+			
 			if ( functionDecl->get_statements() ) {		// empty routine body ?
 				doBeginScope();
@@ -231,6 +294,5 @@
 				// process polymorphic return value
 				retval = 0;
-				std::string typeName;
-				if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
+				if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
 					retval = functionDecl->get_functionType()->get_returnVals().front();
 
@@ -256,4 +318,5 @@
 					findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
 				} // for
+				
 				AdapterMap & adapters = Pass1::adapters.top();
 				for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
@@ -306,4 +369,31 @@
 		}
 
+		Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
+			std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
+			
+			// make a new temporary array
+			Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+			std::stringstream lenGen;
+			lenGen << baseMembers.size();
+			ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );
+			ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );
+
+			// build initializer list for temporary
+			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 ) ) );
+			}
+			arrayTemp->set_init( new ListInit( inits ) );
+
+			// return variable pointing to temporary
+			return new VariableExpr( arrayTemp );
+		}
+		
 		void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			// pass size/align for type variables
@@ -325,5 +415,4 @@
 
 			// 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() );
@@ -334,15 +423,24 @@
 			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 );
+				Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars );
+				if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
+					std::string sizeName = sizeofName( polyBase );
 					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() ) );
+					VariableExpr *fnArgBase = getBaseVar( *fnArg );
+					assert( fnArgBase && ! fnArgBase->get_results().empty() );
+					Type *argBaseType = fnArgBase->get_results().front();
+					arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
 					arg++;
-					arg = appExpr->get_args().insert( arg, new AlignofExpr( argType->clone() ) );
+					arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
 					arg++;
+					if ( dynamic_cast< StructInstType* >( polyBase ) ) {
+						if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
+							arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
+							arg++;
+						} else {
+							throw SemanticError( "Cannot pass non-struct type for generic struct" );
+						}
+					}
 
 					seenTypes.insert( sizeName );
@@ -386,11 +484,38 @@
 		}
 
-		Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) {
-			ResolvExpr::EqvClass eqvClass;
+		void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
+			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");
+				paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
+			}
+		}
+		
+		Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
+			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
+				Type *concrete = env->lookup( typeInst->get_name() );
+				if ( concrete == 0 ) {
+					throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
+				} // if
+				return concrete;
+			} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
+				if ( doClone ) {
+					structType = structType->clone();
+				}
+				replaceParametersWithConcrete( appExpr, structType->get_parameters() );
+				return structType;
+			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
+				if ( doClone ) {
+					unionType = unionType->clone();
+				}
+				replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
+				return unionType;
+			}
+			return type;
+		}
+
+		Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) {
 			assert( env );
-			Type *concrete = env->lookup( typeName );
-			if ( concrete == 0 ) {
-				throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr );
-			} // if
+			Type *concrete = replaceWithConcrete( appExpr, polyType );
 			return addRetParam( appExpr, function, concrete, arg );
 		}
@@ -492,7 +617,4 @@
 			assert( arg );
 			if ( isPolyType( realParam->get_type(), tyVars ) ) {
-//     if ( dynamic_cast< PointerType *>( arg->get_type() ) ) {
-//       return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() );
-//     } else {
 				if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) {
 					UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
@@ -501,5 +623,4 @@
 					return deref;
 				} // if
-//     }
 			} // if
 			return new VariableExpr( param );
@@ -791,7 +912,6 @@
 			std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
 
-			std::string typeName;
-			if ( isPolyRet( function, typeName ) ) {
-				ret = addPolyRetParam( appExpr, function, typeName, arg );
+			if ( ReferenceToType *polyType = isPolyRet( function ) ) {
+				ret = addPolyRetParam( appExpr, function, polyType, arg );
 			} else if ( needsAdapter( function, scopeTyVars ) ) {
 				// std::cerr << "needs adapter: ";
@@ -880,11 +1000,28 @@
 					delete castExpr;
 				} //while
-				TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() );
-				assert( typeInst );
-				std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
-				if ( assignIter == assignOps.end() ) {
-					throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
-				} // if
-				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
+
+				// find assignment operator for (polymorphic) return type
+				DeclarationWithType *assignDecl = 0;
+				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
+					std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
+					if ( assignIter == assignOps.end() ) {
+						throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
+					} // if
+					assignDecl = assignIter->second;
+				} else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
+					ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
+					if ( assignIter == scopedAssignOps.end() ) {
+						throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
+					}
+					DeclarationWithType *functionDecl = assignIter->second;
+					// line below cloned from FixFunction.cc
+					assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
+					                             new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
+					assignDecl->set_mangleName( functionDecl->get_mangleName() );
+				}
+				assert( assignDecl );
+
+				// replace return statement with appropriate assignment to out parameter
+				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
 				Expression *retParm = new NameExpr( retval->get_name() );
 				retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
@@ -927,8 +1064,10 @@
 			// push a copy of the current map
 			adapters.push(adapters.top());
+			scopedAssignOps.beginScope();
 		}
 
 		void Pass1::doEndScope() {
 			adapters.pop();
+			scopedAssignOps.endScope();
 		}
 
@@ -998,6 +1137,5 @@
 
 			// move polymorphic return type to parameter list
-			std::string typeName;
-			if ( isPolyRet( funcType, typeName ) ) {
+			if ( isPolyRet( funcType ) ) {
 				DeclarationWithType *ret = funcType->get_returnVals().front();
 				ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
@@ -1010,4 +1148,6 @@
 			std::list< DeclarationWithType *> inferredParams;
 			ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
+			ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
+			                   new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
 //   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
 			for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
@@ -1036,12 +1176,12 @@
 
 			// add size/align for generic types to parameter list
-			std::set< std::string > seenTypes; //< sizeofName for generic types we've seen
+			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 );
+				Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
+				if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
+					std::string sizeName = sizeofName( polyBase );
 					if ( seenTypes.count( sizeName ) ) continue;
 
-					ObjectDecl *sizeParm, *alignParm;
+					ObjectDecl *sizeParm, *alignParm, *offsetParm;
 					sizeParm = newObj.clone();
 					sizeParm->set_name( sizeName );
@@ -1050,7 +1190,14 @@
 
 					alignParm = newObj.clone();
-					alignParm->set_name( alignofName( parmType ) );
+					alignParm->set_name( alignofName( polyBase ) );
 					last = funcType->get_parameters().insert( last, alignParm );
 					++last;
+
+					if ( dynamic_cast< StructInstType* >( polyBase ) ) {
+						offsetParm = newPtr.clone();
+						offsetParm->set_name( offsetofName( polyBase ) );
+						last = funcType->get_parameters().insert( last, offsetParm );
+						++last;
+					}
 
 					seenTypes.insert( sizeName );
@@ -1066,4 +1213,137 @@
 			scopeTyVars = oldtyVars;
 			return funcType;
+		}
+
+////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
+
+		template< typename DeclClass >
+		DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
+			TyVarMap oldtyVars = scopeTyVars;
+			makeTyVarMap( type, scopeTyVars );
+
+			DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
+
+			scopeTyVars = oldtyVars;
+			return ret;
+		}
+
+		ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
+			return handleDecl( objectDecl, objectDecl->get_type() );
+		}
+
+		DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
+			return handleDecl( functionDecl, functionDecl->get_functionType() );
+		}
+
+		TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
+			return handleDecl( typedefDecl, typedefDecl->get_base() );
+		}
+
+		TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
+			scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
+			return Mutator::mutate( typeDecl );
+		}
+
+		Type * MemberExprFixer::mutate( PointerType *pointerType ) {
+			TyVarMap oldtyVars = scopeTyVars;
+			makeTyVarMap( pointerType, scopeTyVars );
+
+			Type *ret = Mutator::mutate( pointerType );
+
+			scopeTyVars = oldtyVars;
+			return ret;
+		}
+
+		Type * MemberExprFixer::mutate( FunctionType *functionType ) {
+			TyVarMap oldtyVars = scopeTyVars;
+			makeTyVarMap( functionType, scopeTyVars );
+
+			Type *ret = Mutator::mutate( functionType );
+
+			scopeTyVars = oldtyVars;
+			return ret;
+		}
+
+		Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
+			if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
+				if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
+					// change initialization of a polymorphic value object
+					// to allocate storage with alloca
+					Type *declType = objectDecl->get_type();
+					UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
+					alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
+
+					delete objectDecl->get_init();
+
+					std::list<Expression*> designators;
+					objectDecl->set_init( new SingleInit( alloc, designators ) );
+				}
+			}
+			return Mutator::mutate( declStmt );
+		}
+
+		Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
+			// mutate, exiting early if no longer MemberExpr
+			Expression *expr = Mutator::mutate( memberExpr );
+			memberExpr = dynamic_cast< MemberExpr* >( expr );
+			if ( ! memberExpr ) return expr;
+
+			// get declaration for base struct, exiting early if not found
+			int varDepth;
+			VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
+			if ( ! varExpr ) return memberExpr;
+			ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
+			if ( ! objectDecl ) return memberExpr;
+
+			// only mutate member expressions for polymorphic types
+			int tyDepth;
+			Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
+			if ( ! objectType ) return memberExpr;
+
+			// get base aggregate for type so members can be looked up
+			AggregateDecl *memberBase = 0;
+			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
+				memberBase = structType->get_baseStruct();
+			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
+				memberBase = unionType->get_baseUnion();
+			} else return memberExpr;
+
+			// look up numeric index of member in base aggregate
+			DeclarationWithType *memberDecl = memberExpr->get_member();
+			std::list< Declaration* > &baseDecls = memberBase->get_members();
+			std::list< Declaration* >::const_iterator decl = baseDecls.begin();
+			unsigned long i = 0;
+			for( ; decl != baseDecls.end(); ++decl, ++i ) {
+				if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
+
+				if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
+					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) break;
+					else continue;
+				} else break;
+			}
+			if ( decl == baseDecls.end() ) return memberExpr;
+
+			// replace member expression with pointer to base plus offset
+			// get offset for field
+			std::stringstream offset_namer;
+			offset_namer << i;
+			ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
+			UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
+			fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
+			fieldOffset->get_args().push_back( fieldIndex );
+			// build appropriately-dereferenced variable
+			Expression *derefdVar = varExpr->clone();
+			for ( int i = 1; i < varDepth; ++i ) {
+				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+				derefExpr->get_args().push_back( derefdVar );
+				derefdVar = derefExpr;
+			}
+			// add offset to deref'd variable
+			UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
+			fieldLoc->get_args().push_back( derefdVar );
+			fieldLoc->get_args().push_back( fieldOffset );
+
+			delete memberExpr;
+			return fieldLoc;
 		}
 
@@ -1126,22 +1406,4 @@
 			return ret;
 		}
-
-		Statement *Pass3::mutate( DeclStmt *declStmt ) {
-			if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
-				if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
-					// change initialization of a polymorphic value object
-					// to allocate storage with alloca
-					Type *declType = objectDecl->get_type();
-					UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
-					alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
-
-					delete objectDecl->get_init();
-
-					std::list<Expression*> designators;
-					objectDecl->set_init( new SingleInit( alloc, designators ) );
-				}
-			}
-			return Mutator::mutate( declStmt );
-		}
 	} // anonymous namespace
 } // namespace GenPoly
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/GenPoly.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -36,33 +36,11 @@
 	}
 
-	bool isPolyRet( FunctionType *function, std::string &name, const TyVarMap &otherTyVars ) {
-		bool doTransform = false;
+	ReferenceToType *isPolyRet( FunctionType *function ) {
 		if ( ! function->get_returnVals().empty() ) {
-			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( function->get_returnVals().front()->get_type() ) ) {
-	
-				// figure out if the return type is specified by a type parameter
-				for ( std::list< TypeDecl *>::const_iterator tyVar = function->get_forall().begin(); tyVar != function->get_forall().end(); ++tyVar ) {
-					if ( (*tyVar)->get_name() == typeInst->get_name() ) {
-						doTransform = true;
-						name = typeInst->get_name();
-						break;
-					} // if
-				} // for
-				if ( ! doTransform && otherTyVars.find( typeInst->get_name() ) != otherTyVars.end() ) {
-					doTransform = true;
-				} // if
-			} // if
-		} // if
-		return doTransform;
-	}
-
-	bool isPolyRet( FunctionType *function, std::string &name ) {
-		TyVarMap dummyTyVars;
-		return isPolyRet( function, name, dummyTyVars );
-	}
-
-	bool isPolyRet( FunctionType *function, const TyVarMap &otherTyVars ) {
-		std::string dummyString;
-		return isPolyRet( function, dummyString, otherTyVars );
+			TyVarMap forallTypes;
+			makeTyVarMap( function, forallTypes );
+			return (ReferenceToType*)isPolyType( function->get_returnVals().front()->get_type(), forallTypes );
+		} // if
+		return 0;
 	}
 
@@ -149,4 +127,46 @@
 	}
 
+	Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
+		int dummy;
+		if ( ! levels ) { levels = &dummy; }
+		*levels = 0;
+
+		while ( true ) {
+			if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
+				type = ptr->get_base();
+				++(*levels);
+			} else if ( env ) {
+				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
+					if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
+						type = newType;
+					} else break;
+				} else break;
+			} else break;
+		}
+
+		return isPolyType( type, env );
+	}
+	
+	Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {
+		int dummy;
+		if ( ! levels ) { levels = &dummy; }
+		*levels = 0;
+
+		while ( true ) {
+			if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
+				type = ptr->get_base();
+				++(*levels);
+			} else if ( env ) {
+				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) {
+					if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
+						type = newType;
+					} else break;
+				} else break;
+			} else break;
+		}
+
+		return isPolyType( type, tyVars, env );
+	}
+
 	FunctionType * getFunctionType( Type *ty ) {
 		PointerType *ptrType;
@@ -158,4 +178,37 @@
 	}
 
+	VariableExpr * getBaseVar( Expression *expr, int *levels ) {
+		int dummy;
+		if ( ! levels ) { levels = &dummy; }
+		*levels = 0;
+
+		while ( true ) {
+			if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) {
+				return varExpr;
+			} else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) {
+				expr = addressExpr->get_arg();
+			} else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) {
+				// look for compiler-inserted dereference operator
+				NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() );
+				if ( ! fn || fn->get_name() != std::string("*?") ) return 0;
+				expr = *untypedExpr->begin_args();
+			} else break;
+
+			++(*levels);
+		}
+
+		return 0;
+	}
+
+	void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
+		for ( std::list< TypeDecl* >::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
+			assert( *tyVar );
+			tyVarMap[ (*tyVar)->get_name() ] = (*tyVar)->get_kind();
+		}
+		if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
+			makeTyVarMap( pointer->get_base(), tyVarMap );
+		}
+	}
+	
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
 		for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
@@ -172,4 +225,9 @@
 		return std::string( "_alignof_" ) + SymTab::Mangler::mangleType( ty );
 	}
+
+	std::string offsetofName( Type* ty ) {
+		return std::string( "_offsetof_" ) + SymTab::Mangler::mangleType( ty );
+	}
+
 } // namespace GenPoly
 
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/GenPoly.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -20,6 +20,8 @@
 #include <string>
 #include <iostream>
+#include <utility>
 
 #include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
 #include "SynTree/TypeSubstitution.h"
 
@@ -32,7 +34,5 @@
 
 	/// true iff function has polymorphic return type
-	bool isPolyRet( FunctionType *function, std::string &name, const TyVarMap &otherTyVars );
-	bool isPolyRet( FunctionType *function, std::string &name );
-	bool isPolyRet( FunctionType *function, const TyVarMap &otherTyVars );
+	ReferenceToType *isPolyRet( FunctionType *function );
 
 	/// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
@@ -48,7 +48,22 @@
 	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
 
+	/// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type, returns the base type, NULL otherwise;
+	/// N will be stored in levels, if provided, will look up substitution in env if provided
+	Type *hasPolyBase( Type *type, int *levels = 0, const TypeSubstitution *env = 0 );
+
+	/// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type in tyVars, returns the base type, NULL otherwise;
+	/// N will be stored in levels, if provided, will look up substitution in env if provided
+	Type *hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels = 0, 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 );
+	FunctionType *getFunctionType( Type *ty );
 
+	/// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
+	/// N will be stored in levels, if provided
+	VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );
+
+	/// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
+	void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
+	
 	/// Prints type variable map
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
@@ -59,4 +74,7 @@
 	/// Gets the name of the alignof parameter for the type
 	std::string alignofName( Type *ty );
+
+	/// Gets the name of the offsetof parameter for the type
+	std::string offsetofName( Type *ty );
 } // namespace GenPoly
 
Index: src/GenPoly/PolyMutator.cc
===================================================================
--- src/GenPoly/PolyMutator.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/PolyMutator.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -152,15 +152,4 @@
 	}
 
-
-	/* static class method */
-	void PolyMutator::makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
-		for ( std::list< TypeDecl* >::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
-			assert( *tyVar );
-			tyVarMap[ (*tyVar)->get_name() ] = (*tyVar)->get_kind();
-		}
-		if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
-			makeTyVarMap( pointer->get_base(), tyVarMap );
-		}
-	}
 } // namespace GenPoly
 
Index: src/GenPoly/PolyMutator.h
===================================================================
--- src/GenPoly/PolyMutator.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/PolyMutator.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -51,6 +51,4 @@
 		virtual void doBeginScope() {}
 		virtual void doEndScope() {}
-		
-		static void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
 	  protected:
 		void mutateStatementList( std::list< Statement* > &statements );
Index: src/GenPoly/ScopedMap.h
===================================================================
--- src/GenPoly/ScopedMap.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
+++ src/GenPoly/ScopedMap.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -0,0 +1,220 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ScopedMap.h --
+//
+// Author           : Aaron B. Moss
+// Created On       : Wed Dec 2 11:37:00 2015
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Wed Dec 2 11:37:00 2015
+// Update Count     : 1
+//
+
+#ifndef _SCOPEDMAP_H
+#define _SCOPEDMAP_H
+
+#include <iterator>
+#include <map>
+#include <utility>
+#include <vector>
+
+namespace GenPoly {
+	/// A map where the items are placed into nested scopes;
+	/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
+	template<typename Key, typename Value>
+	class ScopedMap {
+		typedef std::map< Key, Value > Scope;
+		typedef std::vector< Scope > ScopeList;
+
+		ScopeList scopes; ///< scoped list of maps
+	public:
+		typedef typename Scope::key_type key_type;
+		typedef typename Scope::mapped_type mapped_type;
+		typedef typename Scope::value_type value_type;
+		typedef typename ScopeList::size_type size_type;
+		typedef typename ScopeList::difference_type difference_type;
+		typedef typename Scope::reference reference;
+		typedef typename Scope::const_reference const_reference;
+		typedef typename Scope::pointer pointer;
+		typedef typename Scope::const_pointer const_pointer;
+		
+		class iterator : public std::iterator< std::bidirectional_iterator_tag,
+		                                       value_type > {
+		friend class ScopedMap;
+		friend class const_iterator;
+			typedef typename std::map< Key, Value >::iterator wrapped_iterator;
+			typedef typename std::vector< std::map< Key, Value > > scope_list;
+			typedef typename scope_list::size_type size_type;
+
+			iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
+				: scopes(&_scopes), it(_it), i(_i) {}
+		public:
+			iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+			iterator& operator= (const iterator &that) {
+				scopes = that.scopes; i = that.i; it = that.it;
+				return *this;
+			}
+			
+			reference operator* () { return *it; }
+			pointer operator-> () { return it.operator->(); }
+
+			iterator& operator++ () {
+				if ( it == (*scopes)[i].end() ) {
+					if ( i == 0 ) return *this;
+					--i;
+					it = (*scopes)[i].begin();
+					return *this;
+				}
+				++it;
+				return *this;
+			}
+			iterator& operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
+
+			iterator& operator-- () {
+				// may fail if this is the begin iterator; allowed by STL spec
+				if ( it == (*scopes)[i].begin() ) {
+					++i;
+					it = (*scopes)[i].end();
+				}
+				--it;
+				return *this;
+			}
+			iterator& operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
+
+			bool operator== (const iterator &that) {
+				return scopes == that.scopes && i == that.i && it == that.it;
+			}
+			bool operator!= (const iterator &that) { return !( *this == that ); }
+
+		private:
+			scope_list const *scopes;
+			wrapped_iterator it;
+			size_type i;
+		};
+
+		class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
+		                                             value_type > {
+		friend class ScopedMap;
+			typedef typename std::map< Key, Value >::iterator wrapped_iterator;
+			typedef typename std::map< Key, Value >::const_iterator wrapped_const_iterator;
+			typedef typename std::vector< std::map< Key, Value > > scope_list;
+			typedef typename scope_list::size_type size_type;
+
+			const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
+				: scopes(&_scopes), it(_it), i(_i) {}
+		public:
+			const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+			const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+			const_iterator& operator= (const iterator &that) {
+				scopes = that.scopes; i = that.i; it = that.it;
+				return *this;
+			}
+			const_iterator& operator= (const const_iterator &that) {
+				scopes = that.scopes; i = that.i; it = that.it;
+				return *this;
+			}
+
+			const_reference operator* () { return *it; }
+			const_pointer operator-> () { return it.operator->(); }
+
+			const_iterator& operator++ () {
+				if ( it == (*scopes)[i].end() ) {
+					if ( i == 0 ) return *this;
+					--i;
+					it = (*scopes)[i].begin();
+					return *this;
+				}
+				++it;
+				return *this;
+			}
+			const_iterator& operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
+
+			const_iterator& operator-- () {
+				// may fail if this is the begin iterator; allowed by STL spec
+				if ( it == (*scopes)[i].begin() ) {
+					++i;
+					it = (*scopes)[i].end();
+				}
+				--it;
+				return *this;
+			}
+			const_iterator& operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
+
+			bool operator== (const const_iterator &that) {
+				return scopes == that.scopes && i == that.i && it == that.it;
+			}
+			bool operator!= (const const_iterator &that) { return !( *this == that ); }
+
+		private:
+			scope_list const *scopes;
+			wrapped_const_iterator it;
+			size_type i;
+		};
+		
+		/// Starts a new scope
+		void beginScope() {
+			Scope scope;
+			scopes.push_back(scope);
+		}
+
+		/// Ends a scope; invalidates any iterators pointing to elements of that scope
+		void endScope() {
+			scopes.pop_back();
+		}
+
+		/// Default constructor initializes with one scope
+		ScopedMap() { beginScope(); }
+
+		iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1); }
+		const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1); }
+		const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1); }
+		iterator end() { return iterator(scopes, scopes[0].end(), 0); }
+		const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
+		const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
+
+		/// Gets the index of the current scope (counted from 1)
+		size_type currentScope() const { return scopes.size(); }
+
+		/// Finds the given key in the outermost scope it occurs; returns end() for none such
+		iterator find( const Key &key ) {
+			for ( size_type i = scopes.size() - 1; ; --i ) {
+				typename Scope::iterator val = scopes[i].find( key );
+				if ( val != scopes[i].end() ) return iterator( scopes, val, i );
+				if ( i == 0 ) break;
+			}
+			return end();
+		}
+		const_iterator find( const Key &key ) const { return const_iterator( find( key ) ); }
+		
+		/// Finds the given key in the outermost scope inside the given scope where it occurs
+		iterator findNext( const_iterator &it, const Key &key ) {
+			if ( it.i == 0 ) return end();
+			for ( size_type i = it.i - 1; ; --i ) {
+				typename Scope::iterator val = scopes[i].find( key );
+				if ( val != scopes[i].end() ) return iterator( scopes, val, i );
+				if ( i == 0 ) break;
+			}
+			return end();
+		}
+		const_iterator findNext( const_iterator &it, const Key &key ) const { return const_iterator( findNext( it, key ) ); }
+
+		/// Inserts the given key-value pair into the outermost scope
+		std::pair< iterator, bool > insert( const value_type &value ) {
+			std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
+			return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
+		}
+		std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
+		
+	};
+} // namespace GenPoly
+
+#endif // _SCOPEDMAP_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/ScrubTyVars.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -27,5 +27,5 @@
 	Type * ScrubTyVars::mutate( TypeInstType *typeInst ) {
 		TyVarMap::const_iterator tyVar = tyVars.find( typeInst->get_name() );
-		if ( doAll || tyVar != tyVars.end() ) {
+		if ( tyVar != tyVars.end() ) {
 			switch ( tyVar->second ) {
 			  case TypeDecl::Any:
@@ -42,4 +42,21 @@
 		} // if
 		return typeInst;
+	}
+
+	Type * ScrubTyVars::mutateAggregateType( Type *ty ) {
+		if ( isPolyType( ty, tyVars ) ) {
+			PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
+			delete ty;
+			return ret;
+		}
+		return ty;
+	}
+	
+	Type * ScrubTyVars::mutate( StructInstType *structInst ) {
+		return mutateAggregateType( structInst );
+	}
+
+	Type * ScrubTyVars::mutate( UnionInstType *unionInst ) {
+		return mutateAggregateType( unionInst );
 	}
 
@@ -65,13 +82,11 @@
 
 	Type * ScrubTyVars::mutate( PointerType *pointer ) {
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( pointer->get_base() ) ) {
-			if ( doAll || tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
-				Type *ret = mutate( typeInst );
-				ret->get_qualifiers() += pointer->get_qualifiers();
-				pointer->set_base( 0 );
-				delete pointer;
-				return ret;
-			} // if
-		} // if
+		if ( Type *polyType = isPolyType( pointer->get_base(), tyVars ) ) {
+			Type *ret = polyType->acceptMutator( *this );
+			ret->get_qualifiers() += pointer->get_qualifiers();
+			pointer->set_base( 0 );
+			delete pointer;
+			return ret;
+		}
 		return Mutator::mutate( pointer );
 	}
Index: src/GenPoly/ScrubTyVars.h
===================================================================
--- src/GenPoly/ScrubTyVars.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/GenPoly/ScrubTyVars.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -27,19 +27,22 @@
 	class ScrubTyVars : public Mutator {
 	  public:
-		ScrubTyVars( bool doAll, const TyVarMap &tyVars ): doAll( doAll ), tyVars( tyVars ) {}
+		ScrubTyVars( const TyVarMap &tyVars ): tyVars( tyVars ) {}
 
-		/// Like scrub( SynTreeClass* ), but only applies to type variables in `tyVars`
+		/// For all polymorphic types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
+		/// and sizeof/alignof expressions with the proper variable
 		template< typename SynTreeClass >
 		static SynTreeClass *scrub( SynTreeClass *target, const TyVarMap &tyVars );
-		/// Replaces dtypes and ftypes with the appropriate void type, and sizeof expressions of polymorphic types with the proper variable
-		template< typename SynTreeClass >
-		static SynTreeClass *scrub( SynTreeClass *target );
-  
+
 		virtual Type* mutate( TypeInstType *typeInst );
-		Expression* mutate( SizeofExpr *szeof );
-		Expression* mutate( AlignofExpr *algnof );
+		virtual Type* mutate( StructInstType *structInst );
+		virtual Type* mutate( UnionInstType *unionInst );
+		virtual Expression* mutate( SizeofExpr *szeof );
+		virtual Expression* mutate( AlignofExpr *algnof );
 		virtual Type* mutate( PointerType *pointer );
+
 	  private:
-		bool doAll;
+		/// Mutates (possibly generic) aggregate types appropriately
+		Type* mutateAggregateType( Type *ty );
+		
 		const TyVarMap &tyVars;
 	};
@@ -48,15 +51,8 @@
 	template< typename SynTreeClass >
 	SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
-		ScrubTyVars scrubber( false, tyVars );
+		ScrubTyVars scrubber( tyVars );
 		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
 	}
 
-	/* static class method */
-	template< typename SynTreeClass >
-	SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target ) {
-		TyVarMap tyVars;
-		ScrubTyVars scrubber( true, tyVars );
-		return static_cast< SynTreeClass* >( target->acceptMutator( scrubber ) );
-	}
 } // namespace GenPoly
 
Index: src/InitTweak/InitModel.h
===================================================================
--- src/InitTweak/InitModel.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/InitTweak/InitModel.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -73,4 +73,5 @@
 			void visit( SizeofExpr * ) { throw 0; }
 			void visit( AlignofExpr * ) { throw 0; }
+			void visit( OffsetofExpr * ) { throw 0; }
 			void visit( AttrExpr * ) { throw 0; }
 			void visit( LogicalExpr * ) { throw 0; }
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -811,4 +811,8 @@
 	}
 
+	void AlternativeFinder::visit( OffsetofExpr *offsetofExpr ) {
+		alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
+	}
+
 	void AlternativeFinder::resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env ) {
 		// assume no polymorphism
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/ResolvExpr/AlternativeFinder.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -56,5 +56,6 @@
 		virtual void visit( ConstantExpr *constantExpr ); 
 		virtual void visit( SizeofExpr *sizeofExpr );
-		virtual void visit( AlignofExpr *sizeofExpr );
+		virtual void visit( AlignofExpr *alignofExpr );
+		virtual void visit( OffsetofExpr *offsetofExpr );
 		virtual void visit( AttrExpr *attrExpr );
 		virtual void visit( LogicalExpr *logicalExpr );
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SymTab/Indexer.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -225,4 +225,10 @@
 			maybeAccept( alignofExpr->get_expr(), *this );
 		}
+	}
+
+	void Indexer::visit( OffsetofExpr *offsetofExpr ) {
+		acceptAllNewScope( offsetofExpr->get_results(), *this );
+		maybeAccept( offsetofExpr->get_type(), *this );
+		maybeAccept( offsetofExpr->get_member(), *this );
 	}
 
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SymTab/Indexer.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -55,4 +55,5 @@
 		virtual void visit( SizeofExpr *sizeofExpr );
 		virtual void visit( AlignofExpr *alignofExpr );
+		virtual void visit( OffsetofExpr *offsetofExpr );
 		virtual void visit( AttrExpr *attrExpr );
 		virtual void visit( LogicalExpr *logicalExpr );
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SymTab/Validate.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -585,4 +585,14 @@
 	}
 
+	template< typename OutputIterator >
+	void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
+		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
+		copy->get_args().push_back( new VariableExpr( dstParam ) );
+		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
+		copy->get_args().push_back( new SizeofExpr( unionType ) );
+
+		*out++ = new ExprStmt( noLabels, copy );
+	}
+
 	//E ?=?(E volatile*, int),
 	//  ?=?(E _Atomic volatile*, int);
@@ -653,7 +663,9 @@
 
 		// Make function polymorphic in same parameters as generic struct, if applicable
+		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > structParams;  // List of matching parameters to put on types
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
+			isGeneric = true;
 			TypeDecl *typeParam = (*param)->clone();
 			assignType->get_forall().push_back( typeParam );
@@ -661,5 +673,5 @@
 		}
 
-		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
+		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
 
@@ -691,10 +703,12 @@
 				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
 					makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
 				} else {
 					makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
 				} // if
 			} // if
 		} // for
-		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 
 		return assignDecl;
@@ -705,7 +719,9 @@
 
 		// Make function polymorphic in same parameters as generic union, if applicable
+		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > unionParams;  // List of matching parameters to put on types
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
+			isGeneric = true;
 			TypeDecl *typeParam = (*param)->clone();
 			assignType->get_forall().push_back( typeParam );
@@ -713,5 +729,5 @@
 		}
 
-		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
+		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
 
@@ -727,11 +743,8 @@
 		assignDecl->fixUniqueId();
 
-		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
-		copy->get_args().push_back( new VariableExpr( dstParam ) );
-		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
-		copy->get_args().push_back( new SizeofExpr( cloneWithParams( refType, unionParams ) ) );
-
-		assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
-		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+		makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
+		if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
+		
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 
 		return assignDecl;
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Expression.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -103,10 +103,10 @@
 SizeofExpr::SizeofExpr( Expression *expr_, Expression *_aname ) :
 		Expression( _aname ), expr(expr_), type(0), isType(false) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ) );
+	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
 SizeofExpr::SizeofExpr( Type *type_, Expression *_aname ) :
 		Expression( _aname ), expr(0), type(type_), isType(true) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ) );
+	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -134,10 +134,10 @@
 AlignofExpr::AlignofExpr( Expression *expr_, Expression *_aname ) :
 		Expression( _aname ), expr(expr_), type(0), isType(false) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ) );
+	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
 AlignofExpr::AlignofExpr( Type *type_, Expression *_aname ) :
 		Expression( _aname ), expr(0), type(type_), isType(true) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ) );
+	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -158,4 +158,38 @@
 	else
 		expr->print(os, indent + 2);
+
+	os << std::endl;
+	Expression::print( os, indent );
+}
+
+OffsetofExpr::OffsetofExpr( Type *type_, DeclarationWithType *member_, Expression *_aname ) :
+		Expression( _aname ), type(type_), member(member_) {
+	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+}
+
+OffsetofExpr::OffsetofExpr( const OffsetofExpr &other ) :
+	Expression( other ), type( maybeClone( other.type ) ), member( maybeClone( other.member ) ) {}
+
+OffsetofExpr::~OffsetofExpr() {
+	delete type;
+	delete member;
+}
+
+void OffsetofExpr::print( std::ostream &os, int indent) const {
+	os << std::string( indent, ' ' ) << "Offsetof Expression on member ";
+
+	if ( member ) {
+		os << member->get_name();
+	} else {
+		os << "<NULL>";
+	}
+
+	os << " of ";
+
+	if ( type ) {
+		type->print(os, indent + 2);
+	} else {
+		os << "<NULL>";
+	}
 
 	os << std::endl;
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Expression.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -319,4 +319,25 @@
 };
 
+/// OffsetofExpr represents an offsetof expression
+class OffsetofExpr : public Expression {
+  public:
+	OffsetofExpr( Type *type, DeclarationWithType *member, Expression *_aname = 0 );
+	OffsetofExpr( const OffsetofExpr &other );
+	virtual ~OffsetofExpr();
+
+	Type *get_type() const { return type; }
+	void set_type( Type *newValue ) { type = newValue; }
+	DeclarationWithType *get_member() const { return member; }
+	void set_member( DeclarationWithType *newValue ) { member = newValue; }
+
+	virtual OffsetofExpr *clone() const { return new OffsetofExpr( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+  private:
+	Type *type;
+	DeclarationWithType *member;
+};
+
 /// AttrExpr represents an @attribute expression (like sizeof, but user-defined)
 class AttrExpr : public Expression {
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Initializer.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -55,5 +55,5 @@
 class SingleInit : public Initializer {
   public:
-	SingleInit( Expression *value, std::list< Expression *> &designators );
+	SingleInit( Expression *value, std::list< Expression *> &designators = *(new std::list<Expression *>()) );
 	SingleInit( const SingleInit &other );
 	virtual ~SingleInit();
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Mutator.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -261,4 +261,11 @@
 }
 
+Expression *Mutator::mutate( OffsetofExpr *offsetofExpr ) {
+	mutateAll( offsetofExpr->get_results(), *this );
+	offsetofExpr->set_type( maybeMutate( offsetofExpr->get_type(), *this ) );
+	offsetofExpr->set_member( maybeMutate( offsetofExpr->get_member(), *this ) );
+	return offsetofExpr;
+}
+
 Expression *Mutator::mutate( AttrExpr *attrExpr ) {
 	mutateAll( attrExpr->get_results(), *this );
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Mutator.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -65,4 +65,5 @@
 	virtual Expression* mutate( SizeofExpr *sizeofExpr );
 	virtual Expression* mutate( AlignofExpr *alignofExpr );
+	virtual Expression* mutate( OffsetofExpr *offsetofExpr );
 	virtual Expression* mutate( AttrExpr *attrExpr );
 	virtual Expression* mutate( LogicalExpr *logicalExpr );
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/SynTree.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -70,4 +70,5 @@
 class SizeofExpr;
 class AlignofExpr;
+class OffsetofExpr;
 class AttrExpr;
 class LogicalExpr;
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Visitor.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -219,4 +219,10 @@
 }
 
+void Visitor::visit( OffsetofExpr *offsetofExpr ) {
+	acceptAll( offsetofExpr->get_results(), *this );
+	maybeAccept( offsetofExpr->get_type(), *this );
+	maybeAccept( offsetofExpr->get_member(), *this );
+}
+
 void Visitor::visit( AttrExpr *attrExpr ) {
 	acceptAll( attrExpr->get_results(), *this );
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/SynTree/Visitor.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -65,4 +65,5 @@
 	virtual void visit( SizeofExpr *sizeofExpr );
 	virtual void visit( AlignofExpr *alignofExpr );
+	virtual void visit( OffsetofExpr *offsetofExpr );
 	virtual void visit( AttrExpr *attrExpr );
 	virtual void visit( LogicalExpr *logicalExpr );
Index: src/Tuples/FlattenTuple.cc
===================================================================
--- src/Tuples/FlattenTuple.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/Tuples/FlattenTuple.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -47,4 +47,5 @@
 	void FlattenTuple::CollectArgs::visit( SizeofExpr        *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
 	void FlattenTuple::CollectArgs::visit( AlignofExpr       *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( OffsetofExpr      *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
 	void FlattenTuple::CollectArgs::visit( AttrExpr          *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
 	void FlattenTuple::CollectArgs::visit( LogicalExpr       *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
Index: src/Tuples/FlattenTuple.h
===================================================================
--- src/Tuples/FlattenTuple.h	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/Tuples/FlattenTuple.h	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -43,4 +43,5 @@
 			virtual void visit( SizeofExpr * );
 			virtual void visit( AlignofExpr * );
+			virtual void visit( OffsetofExpr * );
 			virtual void visit( AttrExpr * );
 			virtual void visit( LogicalExpr * );
Index: src/main.cc
===================================================================
--- src/main.cc	(revision d3b7937ae7ab8afece0824b5729b7e86a9f0bd63)
+++ src/main.cc	(revision ae8b94256813adfe7582e0fabf10bdd0d8c7b864)
@@ -24,5 +24,4 @@
 #include "SynTree/Declaration.h"
 #include "SynTree/Visitor.h"
-#include "GenPoly/InstantiateGeneric.h"
 #include "GenPoly/Lvalue.h"
 #include "GenPoly/Specialize.h"
@@ -271,6 +270,4 @@
 		}
 
-		OPTPRINT( "instantiateGeneric" )
-		GenPoly::instantiateGeneric( translationUnit );
 		OPTPRINT( "copyParams" );
 		GenPoly::copyParams( translationUnit );
@@ -281,5 +278,5 @@
 		OPTPRINT( "box" )
 		GenPoly::box( translationUnit );
-
+		
 		// print tree right before code generation
 		if ( codegenp ) {
