Index: src/Common/Examine.cc
===================================================================
--- src/Common/Examine.cc	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ src/Common/Examine.cc	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -0,0 +1,58 @@
+//
+// 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.
+//
+// Examine.h --
+//
+// Author           : Andrew Beach
+// Created On       : Wed Sept 2 14:02 2020
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Sep  8 12:15 2020
+// Update Count     : 0
+//
+
+#include "Common/Examine.h"
+
+#include "CodeGen/OperatorTable.h"
+
+DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) {
+	if (func->name != "main") return nullptr;
+	if (func->type->parameters.size() != 1) return nullptr;
+
+	auto param = func->type->parameters.front();
+
+	auto type = dynamic_cast<ReferenceType * >(param->get_type());
+	if (!type) return nullptr;
+
+	auto obj = dynamic_cast<StructInstType *>(type->base);
+	if (!obj) return nullptr;
+
+	if (kind != obj->baseStruct->kind) return nullptr;
+
+	return param;
+}
+
+namespace {
+	Type * getDestructorParam( FunctionDecl * func ) {
+		if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
+
+		auto params = func->type->parameters;
+		if ( 1 != params.size() ) return nullptr;
+
+		auto ref = dynamic_cast<ReferenceType *>( params.front()->get_type() );
+		if ( ref ) {
+			return ref->base;
+		}
+		return nullptr;
+	}
+}
+
+bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl ) {
+	if ( Type * type = getDestructorParam( func ) ) {
+		auto stype = dynamic_cast<StructInstType *>( type );
+		return stype && stype->baseStruct == type_decl;
+	}
+	return false;
+}
Index: src/Common/Examine.h
===================================================================
--- src/Common/Examine.h	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ src/Common/Examine.h	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -0,0 +1,23 @@
+//
+// 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.
+//
+// Examine.h --
+//
+// Author           : Andrew Beach
+// Created On       : Wed Sept 2 13:57 2020
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Sep  8 12:08 2020
+// Update Count     : 0
+//
+
+#include "SynTree/Declaration.h"
+
+/// Check if this is a main function for a type of an aggregate kind.
+DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind );
+// Returns a pointer to the parameter if true, nullptr otherwise.
+
+/// Check if this function is a destructor for the given structure.
+bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl );
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision e6b42e7a226ea0d0e4d4f46d30734a2ee84d96cb)
+++ src/Common/module.mk	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -22,4 +22,6 @@
       Common/ErrorObjects.h \
       Common/Eval.cc \
+      Common/Examine.cc \
+      Common/Examine.h \
       Common/FilterCombos.h \
       Common/Indenter.h \
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision e6b42e7a226ea0d0e4d4f46d30734a2ee84d96cb)
+++ src/Concurrency/Keywords.cc	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -19,4 +19,7 @@
 #include <string>                         // for string, operator==
 
+#include <iostream>
+
+#include "Common/Examine.h"               // for isMainFor
 #include "Common/PassVisitor.h"           // for PassVisitor
 #include "Common/SemanticError.h"         // for SemanticError
@@ -34,8 +37,13 @@
 #include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
 #include "SynTree/Visitor.h"              // for Visitor, acceptAll
+#include "Virtual/Tables.h"
 
 class Attribute;
 
 namespace Concurrency {
+	inline static std::string getVTableName( std::string const & exception_name ) {
+		return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
+	}
+
 	//=============================================================================================
 	// Pass declarations
@@ -54,6 +62,10 @@
 	  public:
 
-	  	ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) :
-		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {}
+		ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name,
+			std::string&& getter_name, std::string&& context_error, std::string&& exception_name,
+			bool needs_main, AggregateDecl::Aggregate cast_target ) :
+		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
+		  context_error( context_error ), vtable_name( getVTableName( exception_name ) ),
+		  needs_main( needs_main ), cast_target( cast_target ) {}
 
 		virtual ~ConcurrentSueKeyword() {}
@@ -63,4 +75,5 @@
 
 		void handle( StructDecl * );
+		void addVtableForward( StructDecl * );
 		FunctionDecl * forwardDeclare( StructDecl * );
 		ObjectDecl * addField( StructDecl * );
@@ -76,4 +89,5 @@
 		const std::string getter_name;
 		const std::string context_error;
+		const std::string vtable_name;
 		bool needs_main;
 		AggregateDecl::Aggregate cast_target;
@@ -81,4 +95,5 @@
 		StructDecl   * type_decl = nullptr;
 		FunctionDecl * dtor_decl = nullptr;
+		StructDecl * vtable_decl = nullptr;
 	};
 
@@ -101,4 +116,5 @@
 			"get_thread",
 			"thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
+			"",
 			true,
 			AggregateDecl::Thread
@@ -133,4 +149,5 @@
 			"get_coroutine",
 			"coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
+			"CoroutineCancelled",
 			true,
 			AggregateDecl::Coroutine
@@ -167,4 +184,5 @@
 			"get_monitor",
 			"monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
+			"",
 			false,
 			AggregateDecl::Monitor
@@ -198,4 +216,5 @@
 			"get_generator",
 			"Unable to find builtin type $generator\n",
+			"",
 			true,
 			AggregateDecl::Generator
@@ -231,5 +250,4 @@
 
 	private:
-		DeclarationWithType * is_main( FunctionDecl * );
 		bool is_real_suspend( FunctionDecl * );
 
@@ -359,22 +377,30 @@
 			handle( decl );
 		}
+		else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
+			vtable_decl = decl;
+		}
+		// Might be able to get ride of is target.
+		assert( is_target(decl) == (cast_target == decl->kind) );
 		return decl;
 	}
 
 	DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
-		if( !type_decl ) return decl;
-		if( !CodeGen::isDestructor( decl->name ) ) return decl;
-
-		auto params = decl->type->parameters;
-		if( params.size() != 1 ) return decl;
-
-		auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() );
-		if( !type ) return decl;
-
-		auto stype = dynamic_cast<StructInstType*>( type->base );
-		if( !stype ) return decl;
-		if( stype->baseStruct != type_decl ) return decl;
-
-		if( !dtor_decl ) dtor_decl = decl;
+		if ( type_decl && isDestructorFor( decl, type_decl ) )
+			dtor_decl = decl;
+		else if ( vtable_name.empty() )
+			;
+		else if ( auto param = isMainFor( decl, cast_target ) ) {
+			// This should never trigger.
+			assert( vtable_decl );
+			// Should be safe because of isMainFor.
+			StructInstType * struct_type = static_cast<StructInstType *>(
+				static_cast<ReferenceType *>( param->get_type() )->base );
+			assert( struct_type );
+
+			declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
+				new TypeExpr( struct_type->clone() ),
+			}, struct_type, nullptr ) );
+		}
+
 		return decl;
 	}
@@ -400,7 +426,19 @@
 		if( !dtor_decl ) SemanticError( decl, context_error );
 
+		addVtableForward( decl );
 		FunctionDecl * func = forwardDeclare( decl );
 		ObjectDecl * field = addField( decl );
 		addRoutines( field, func );
+	}
+
+	void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
+		if ( vtable_decl ) {
+			declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
+				new TypeExpr( new StructInstType( noQualifiers, decl ) ),
+			} ) );
+		// Its only an error if we want a vtable and don't have one.
+		} else if ( ! vtable_name.empty() ) {
+			SemanticError( decl, context_error );
+		}
 	}
 
@@ -528,21 +566,4 @@
 	// Suspend keyword implementation
 	//=============================================================================================
-	DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) {
-		if(func->name != "main") return nullptr;
-		if(func->type->parameters.size() != 1) return nullptr;
-
-		auto param = func->type->parameters.front();
-
-		auto type  = dynamic_cast<ReferenceType * >(param->get_type());
-		if(!type) return nullptr;
-
-		auto obj   = dynamic_cast<StructInstType *>(type->base);
-		if(!obj) return nullptr;
-
-		if(!obj->baseStruct->is_generator()) return nullptr;
-
-		return param;
-	}
-
 	bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
 		if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
@@ -565,5 +586,5 @@
 
 		// Is this the main of a generator?
-		auto param = is_main( func );
+		auto param = isMainFor( func, AggregateDecl::Aggregate::Generator );
 		if(!param) return;
 
@@ -1033,2 +1054,3 @@
 // tab-width: 4 //
 // End: //
+
Index: src/Virtual/Tables.cc
===================================================================
--- src/Virtual/Tables.cc	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ src/Virtual/Tables.cc	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -0,0 +1,117 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Tables.cc --
+//
+// Author           : Andrew Beach
+// Created On       : Mon Aug 31 11:11:00 2020
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Sep  3 14:56:00 2020
+// Update Count     : 0
+//
+
+#include <SynTree/Declaration.h>
+#include <SynTree/Expression.h>
+#include <SynTree/Type.h>
+
+namespace Virtual {
+
+std::string vtableTypeName( std::string const & name ) {
+	return name + "_vtable";
+}
+
+std::string instanceName( std::string const & name ) {
+	return std::string("_") + name + "_instance";
+}
+
+std::string vtableInstanceName( std::string const & name ) {
+	return instanceName( vtableTypeName( name ) );
+}
+
+bool isVTableInstanceName( std::string const & name ) {
+	// There are some delicate length calculations here.
+	return 17 < name.size() && '_' == name[0] &&
+		std::string("_vtable_instance") == name.substr(1, name.size() - 17);
+}
+
+// Fuse base polymorphic declaration and forall arguments into a new type.
+static StructInstType * vtableInstType(
+		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
+	assert( parameters.size() == polyDecl->parameters.size() );
+	StructInstType * type = new StructInstType(
+			Type::Qualifiers( /* Type::Const */ ), polyDecl );
+	type->parameters = std::move( parameters );
+	return type;
+}
+
+static ObjectDecl * makeVtableDeclaration(
+		StructInstType * type, Initializer * init ) {
+	std::string const & name = instanceName( type->name );
+	Type::StorageClasses storage = noStorageClasses;
+	if ( nullptr == init ) {
+		storage.is_extern = true;
+	}
+	return new ObjectDecl(
+		name,
+		storage,
+		LinkageSpec::Cforall,
+		nullptr,
+		type,
+		init
+	);
+}
+
+ObjectDecl * makeVtableForward( StructInstType * type ) {
+	return makeVtableDeclaration( type, nullptr );
+}
+
+ObjectDecl * makeVtableForward(
+		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
+	return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) );
+}
+
+ObjectDecl * makeVtableInstance(
+		StructInstType * vtableType, Type * vobject_type, Initializer * init ) {
+	StructDecl * vtableStruct = vtableType->baseStruct;
+	// Build the initialization
+	if ( nullptr == init ) {
+		std::list< Initializer * > inits;
+
+		// This is going to have to be run before the resolver to connect expressions.
+		for ( auto field : vtableStruct->members ) {
+			if ( std::string( "parent" ) == field->name ) {
+				// This will not work with polymorphic state.
+				auto oField = strict_dynamic_cast< ObjectDecl * >( field );
+				auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
+				auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
+				std::string const & parentInstance = instanceName( parentType->name );
+				inits.push_back(
+						new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
+			} else if ( std::string( "size" ) == field->name ) {
+				inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) );
+			} else if ( std::string( "align" ) == field->name ) {
+				inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) );
+			} else {
+				inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
+			}
+		}
+		init = new ListInit( inits );
+	// This should initialize everything except the parent pointer, the
+	// size-of and align-of fields. These should be inserted.
+	} else {
+		assert(false);
+	}
+	return makeVtableDeclaration( vtableType, init );
+}
+
+ObjectDecl * makeVtableInstance(
+		StructDecl * polyDecl, std::list< Expression * > && parameters,
+		Type * vobject, Initializer * init ) {
+	return makeVtableInstance(
+		vtableInstType( polyDecl, std::move( parameters ) ), vobject, init );
+}
+
+}
Index: src/Virtual/Tables.h
===================================================================
--- src/Virtual/Tables.h	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ src/Virtual/Tables.h	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -0,0 +1,52 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Tables.h --
+//
+// Author           : Andrew Beach
+// Created On       : Mon Aug 31 11:07:00 2020
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Sep  1 14:29:00 2020
+// Update Count     : 0
+//
+
+#include <list>  // for list
+
+class Declaration;
+class StructDecl;
+class Expression;
+
+namespace Virtual {
+
+std::string vtableTypeName( std::string const & type_name );
+std::string instanceName( std::string const & vtable_name );
+std::string vtableInstanceName( std::string const & type_name );
+bool isVTableInstanceName( std::string const & name );
+
+/// Converts exceptions into regular structures.
+//void ( std::list< Declaration * > & translationUnit );
+
+ObjectDecl * makeVtableForward( StructInstType * );
+ObjectDecl * makeVtableForward( StructDecl *, std::list< Expression * > && );
+/* Create a forward definition of a vtable of the given type.
+ *
+ * Instead of the virtual table type you may provide the declaration and all
+ * the forall parameters.
+ */
+
+ObjectDecl * makeVtableInstance( StructInstType *, Type *, Initializer * );
+ObjectDecl * makeVtableInstance(
+	StructDecl *, std::list< Expression * > &&, Type *, Initializer * );
+/* Create an initialized definition of a vtable.
+ *
+ * The parameters are the virtual table type (or the base declaration and the
+ * forall parameters), the object type and optionally an initializer.
+ *
+ * Instead of the virtual table type you may provide the declaration and all
+ * the forall parameters.
+ */
+
+}
Index: src/Virtual/module.mk
===================================================================
--- src/Virtual/module.mk	(revision e6b42e7a226ea0d0e4d4f46d30734a2ee84d96cb)
+++ src/Virtual/module.mk	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
@@ -15,3 +15,6 @@
 ###############################################################################
 
-SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h
+SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h \
+	Virtual/Tables.cc Virtual/Tables.h
+
+SRCDEMANGLE += Virtual/Tables.cc
