Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 63db3d762d0c667527bfc924b6af64374b1399b2)
+++ src/GenPoly/Box.cc	(revision cdec5af734d50032d94d1ef278c504c44b79ef73)
@@ -14,5 +14,7 @@
 //
 
+#include <map>
 #include <set>
+#include <sstream>
 #include <stack>
 #include <string>
@@ -20,4 +22,5 @@
 #include <algorithm>
 #include <cassert>
+#include <utility>
 
 #include "Box.h"
@@ -28,4 +31,5 @@
 #include "Parser/ParseNode.h"
 
+#include "SynTree/Constant.h"
 #include "SynTree/Type.h"
 #include "SynTree/Expression.h"
@@ -50,8 +54,21 @@
 		FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
 
+		/// Cache for layout struct decls
+		class LayoutStructDecls {
+		public:
+			/// Gets the layout struct declaration for a given number of members (0 for non-generic); creates declarations as needed.
+			/// Declarations are allocated with "new", not freed on LayoutStructDecls destruction
+			StructDecl* get( int members );
+			/// adds all struct declarations to the translation unit
+			void addToTranslationUnit( std::list< Declaration* >& translationUnit );
+		private:
+			/// Layout struct declarations, indexed by number of members in the generic struct (0 for non-generic)
+			std::map< int, StructDecl* > decls;
+		};
+
 		/// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
 		class Pass1 : public PolyMutator {
 		  public:
-			Pass1();
+			Pass1( LayoutStructDecls &layoutDecls );
 			virtual Expression *mutate( ApplicationExpr *appExpr );
 			virtual Expression *mutate( AddressExpr *addrExpr );
@@ -87,4 +104,5 @@
 			bool useRetval;
 			UniqueName tempNamer;
+			LayoutStructDecls &layoutDecls;
 		};
 
@@ -92,5 +110,5 @@
 		class Pass2 : public PolyMutator {
 		  public:
-			Pass2();
+			Pass2( LayoutStructDecls &layoutDecls );
 			template< typename DeclClass >
 			DeclClass *handleDecl( DeclClass *decl, Type *type );
@@ -105,4 +123,5 @@
   
 			std::map< UniqueId, std::string > adapterName;
+			LayoutStructDecls &layoutDecls;
 		};
 
@@ -110,4 +129,5 @@
 		class Pass3 : public PolyMutator {
 		  public:
+			Pass3( LayoutStructDecls &layoutDecls );
 			template< typename DeclClass >
 			DeclClass *handleDecl( DeclClass *decl, Type *type );
@@ -120,4 +140,5 @@
 			virtual Type *mutate( FunctionType *funcType );
 		  private:
+			LayoutStructDecls &layoutDecls;
 		};
 
@@ -134,10 +155,53 @@
 
 	void box( std::list< Declaration *>& translationUnit ) {
-		Pass1 pass1;
-		Pass2 pass2;
-		Pass3 pass3;
+		LayoutStructDecls layoutStructs;
+		Pass1 pass1( layoutStructs );
+		Pass2 pass2( layoutStructs );
+		Pass3 pass3( layoutStructs );
 		mutateAll( translationUnit, pass1 );
 		mutateAll( translationUnit, pass2 );
 		mutateAll( translationUnit, pass3 );
+		layoutStructs.addToTranslationUnit( translationUnit );
+	}
+
+	//////////////////////////////////// LayoutStructDecls //////////////////////////////////////////////
+
+	namespace {
+		StructDecl* LayoutStructDecls::get( int members ) {
+			// Attempt to read declaration already in map
+			std::map< int, StructDecl* >::iterator decl = decls.find( members );
+			if ( decl != decls.end() ) return decl->second;
+
+			// Insert if not found
+			std::string member_str;
+			if ( members > 0 ) {
+				std::stringstream ss;
+				ss << members;
+				member_str = ss.str();
+			}
+			StructDecl *newDecl = new StructDecl( std::string("_layout") + member_str );
+
+			newDecl->get_members().push_back(
+					new ObjectDecl( "size", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ) );
+			newDecl->get_members().push_back(
+					new ObjectDecl( "align", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ) );
+			if ( members > 0 ) {
+				ArrayType *aType =
+						new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ),
+									   new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), member_str ) ), false, false );
+				newDecl->get_members().push_back(
+					new ObjectDecl( "offsets", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, aType, 0 ) );
+			}
+
+			decls.insert( std::make_pair( members, newDecl ) );
+
+			return newDecl;
+		}
+
+		void LayoutStructDecls::addToTranslationUnit( std::list< Declaration* >& translationUnit ) {
+			for ( std::map< int, StructDecl* >::reverse_iterator decl = decls.rbegin(); decl != decls.rend(); ++decl ) {
+				translationUnit.push_front( decl->second );
+			}
+		}
 	}
 
@@ -181,6 +245,6 @@
 		}
 
-		Pass1::Pass1()
-			: useRetval( false ), tempNamer( "_temp" ) {
+		Pass1::Pass1( LayoutStructDecls &layoutDecls )
+			: useRetval( false ), tempNamer( "_temp" ), layoutDecls( layoutDecls ) {
 			adapters.push(AdapterMap());
 		}
@@ -936,5 +1000,5 @@
 ////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
 
-		Pass2::Pass2() {}
+		Pass2::Pass2( LayoutStructDecls &layoutDecls ) : layoutDecls(layoutDecls) {}
 
 		void Pass2::addAdapters( FunctionType *functionType ) {
@@ -1040,4 +1104,6 @@
 ////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
 
+		Pass3::Pass3( LayoutStructDecls &layoutDecls ) : layoutDecls(layoutDecls) {}
+
 		template< typename DeclClass >
 		DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
