Index: trunk/abdev/BasicCompiler32/Compile_ProcOp.cpp
===================================================================
--- trunk/abdev/BasicCompiler32/Compile_ProcOp.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler32/Compile_ProcOp.cpp	(revision 282)
@@ -499,16 +499,32 @@
 			//仮想関数テーブルを初期化
 			if( compiler.pCompilingClass->IsExistVirtualFunctions()
-				&& !compiler.pCompilingClass->IsAbstract() ){
-					//関数テーブルに値をセット
-					int offset = (int)compiler.pCompilingClass->GetVtblGlobalOffset();
-
-					//mov eax,offset
-					compiler.codeGenerator.op_mov_RV( REG_EAX, offset, Schedule::DataTable );
-
-					//Thisポインタをecxにコピー
-					SetThisPtrToReg(REG_ECX);
-
-					//mov dword ptr[ecx],eax
-					compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EAX, REG_ECX, 0, MOD_BASE );
+				&& !compiler.pCompilingClass->IsAbstract() )
+			{
+				// mov eax,vtblAddress
+				compiler.codeGenerator.op_mov_RV_vtbl( REG_EAX, compiler.pCompilingClass );
+
+				/* TODO: 消す
+				//関数テーブルに値をセット
+				int offset = (int)compiler.pCompilingClass->GetVtblGlobalOffset();
+
+				//mov eax,offset
+				compiler.codeGenerator.op_mov_RV( REG_EAX, offset, Schedule::DataTable );
+				*/
+
+				//Thisポインタをecxにコピー
+				SetThisPtrToReg(REG_ECX);
+
+				//mov dword ptr[ecx],eax
+				compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EAX, REG_ECX, 0, MOD_BASE );
+
+
+				// 仮想関数になるメソッドに使用チェックをつける
+				BOOST_FOREACH( const CMethod *pMethod, compiler.pCompilingClass->GetMethods() )
+				{
+					if( pMethod->IsVirtual() )
+					{
+						pMethod->GetUserProc().Using();
+					}
+				}
 			}
 		}
Index: trunk/abdev/BasicCompiler32/MakePeHdr.cpp
===================================================================
--- trunk/abdev/BasicCompiler32/MakePeHdr.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler32/MakePeHdr.cpp	(revision 282)
@@ -509,8 +509,16 @@
 
 
+	/////////////////////////////////////////////////////////////////
+	// vtblの構築
+	/////////////////////////////////////////////////////////////////
+
+	compiler.GetObjectModule().meta.GetClasses().GenerateVTables();
+
+
 
 	////////////////////////////////
 	// ここで一旦ログを取る
 	////////////////////////////////
+
 	Diagnose();
 
@@ -1065,4 +1073,5 @@
 	compiler.linker.ResolveUserProcSchedules( MemPos_CodeSection );
 	compiler.linker.ResolveGlobalVarSchedules( MemPos_RWSection );
+	compiler.linker.ResolveVtblSchedule( MemPos_DataSection );
 
 
Index: trunk/abdev/BasicCompiler32/x86CodeGenerator.cpp
===================================================================
--- trunk/abdev/BasicCompiler32/x86CodeGenerator.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler32/x86CodeGenerator.cpp	(revision 282)
@@ -1311,2 +1311,12 @@
 	pNativeCode->PutUserProcSchedule( pUserProc, false );
 }
+void CodeGenerator::op_mov_RV_vtbl( int reg, const CClass *pClass )
+{
+	// mov reg,vtblAddress
+
+	//オペコード、レジスタ
+	pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) );
+
+	//DISP32
+	pNativeCode->PutVtblSchedule( pClass );
+}
Index: trunk/abdev/BasicCompiler_Common/include/Class.h
===================================================================
--- trunk/abdev/BasicCompiler_Common/include/Class.h	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/include/Class.h	(revision 282)
@@ -360,4 +360,5 @@
 	int GetFuncNumInVtbl( const UserProc *pUserProc ) const;
 	LONG_PTR GetVtblGlobalOffset(void) const;
+	void GenerateVTables();
 	void ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection);
 	bool IsAbstract() const;
@@ -387,4 +388,5 @@
 	virtual void CollectClassesForNameOnly( const BasicSource &source );
 
+	void GenerateVTables();
 	void ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection);
 
Index: trunk/abdev/BasicCompiler_Common/include/CodeGenerator.h
===================================================================
--- trunk/abdev/BasicCompiler_Common/include/CodeGenerator.h	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/include/CodeGenerator.h	(revision 282)
@@ -448,4 +448,5 @@
 	void op_ret( short stackFrameSize );
 	void op_addressof( int reg, const UserProc *pUserProc );
+	void op_mov_RV_vtbl( int reg, const CClass *pClass );
 #endif
 
Index: trunk/abdev/BasicCompiler_Common/include/Linker.h
===================================================================
--- trunk/abdev/BasicCompiler_Common/include/Linker.h	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/include/Linker.h	(revision 282)
@@ -34,4 +34,7 @@
 	void ResolveGlobalVarSchedules( long rwSectionBaseOffset );
 
+	// vtblスケジュール
+	void ResolveVtblSchedule( long dataSectionBaseOffset );
+
 	// リンク
 	void Link( ObjectModule &masterObjectModule );
Index: trunk/abdev/BasicCompiler_Common/include/NativeCode.h
===================================================================
--- trunk/abdev/BasicCompiler_Common/include/NativeCode.h	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/include/NativeCode.h	(revision 282)
@@ -21,4 +21,5 @@
 		AddressOf,		// ユーザ定義関数位置スケジュール
 		DllProc,		// DLL関数位置スケジュール
+		Vtbl,			// vtblスケジュール
 	};
 
@@ -31,4 +32,5 @@
 		const ::UserProc *pUserProc;
 		const ::DllProc *pDllProc;
+		const ::CClass *pClass;
 	};
 
@@ -52,4 +54,7 @@
 			ar & boost::serialization::make_nvp("pDllProc", const_cast<::DllProc *&>(pDllProc));
 			break;
+		case Vtbl:
+			ar & boost::serialization::make_nvp("pClass", const_cast<::CClass *&>(pClass));
+			break;
 		default:
 			ar & BOOST_SERIALIZATION_NVP( lpValue );
@@ -80,4 +85,10 @@
 	{
 	}
+	Schedule( const ::CClass *pClass, long offset )
+		: type( Schedule::Vtbl )
+		, offset( offset )
+		, pClass( pClass )
+	{
+	}
 	~Schedule()
 	{
@@ -111,4 +122,12 @@
 		}
 		return *pUserProc;
+	}
+	const ::CClass &GetClass() const
+	{
+		if( type != Schedule::Vtbl )
+		{
+			SetError();
+		}
+		return *pClass;
 	}
 
@@ -360,4 +379,5 @@
 	void PutUserProcSchedule( const UserProc *pUserProc, bool isCall );
 	void PutDllProcSchedule( const DllProc *pDllProc );
+	void PutVtblSchedule( const CClass *pClass );
 	void Put( short s )
 	{
Index: trunk/abdev/BasicCompiler_Common/include/Source.h
===================================================================
--- trunk/abdev/BasicCompiler_Common/include/Source.h	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/include/Source.h	(revision 282)
@@ -176,5 +176,5 @@
 		bool isEqualBasbuf = false;
 		extern char *basbuf;
-		if( basbuf == buffer )
+		if( basbuf == buffer + 2 )
 		{
 			isEqualBasbuf = true;
Index: trunk/abdev/BasicCompiler_Common/src/Class.cpp
===================================================================
--- trunk/abdev/BasicCompiler_Common/src/Class.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/src/Class.cpp	(revision 282)
@@ -720,5 +720,62 @@
 	return vtbl_offset;
 }
+void CClass::GenerateVTables()
+{
+	if( IsAbstract() )
+	{
+		// 抽象クラスは無視
+		return;
+	}
+	if( !IsUsing() )
+	{
+		// 使われていないクラスは無視
+		return;
+	}
+
+	const UserProc **ppsi;
+	ppsi=(const UserProc **)malloc(GetVtblNum()*sizeof(UserProc *));
+
+	//関数テーブルに値をセット
+	int i2 = 0;
+	BOOST_FOREACH( const CMethod *pMethod, methods ){
+		if(pMethod->IsVirtual()){
+			if( !pMethod->GetUserProc().IsUsing() )
+			{
+				ts((char *)pMethod->GetUserProc().GetFullName().c_str());
+			}
+			pMethod->GetUserProc().Using();
+
+			if(pMethod->IsAbstract()){
+				extern int cp;
+				SmoothieException::Throw(300,NULL,cp);
+
+				ppsi[i2]=0;
+			}
+			else{
+				ppsi[i2]=&pMethod->GetUserProc();
+			}
+			i2++;
+		}
+	}
+
+	vtbl_offset=compiler.GetObjectModule().dataTable.AddBinary((void *)ppsi,GetVtblNum()*sizeof(LONG_PTR));
+
+	for( int i=0; i < GetVtblNum(); i++ ){
+		pobj_Reloc->AddSchedule_DataSection(vtbl_offset+i*sizeof(LONG_PTR));
+	}
+
+	free(ppsi);
+}
 void CClass::ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection){
+	if( IsAbstract() )
+	{
+		// 抽象クラスは無視
+		return;
+	}
+	if( !IsUsing() )
+	{
+		// 使われていないクラスは無視
+		return;
+	}
 	if(vtbl_offset==-1) return;
 
@@ -731,4 +788,10 @@
 		pUserProc=(UserProc *)pVtbl[i];
 		if(!pUserProc) continue;
+
+		if( pUserProc->GetBeginOpAddress() == 0
+			&& pUserProc->GetEndOpAddress() == 0 )
+		{
+			Jenga::Throw( "未解決の仮想関数が存在する" );
+		}
 
 		pVtbl[i]=pUserProc->GetBeginOpAddress()+ImageBase+MemPos_CodeSection;
@@ -908,4 +971,14 @@
 				}
 		}
+	}
+}
+
+void Classes::GenerateVTables()
+{
+	Iterator_Reset();
+	while( Iterator_HasNext() )
+	{
+		CClass *pClass = Iterator_GetNext();
+		pClass->GenerateVTables();
 	}
 }
@@ -1615,4 +1688,13 @@
 		pParentClass->Using();
 
+		// 仮想関数になるメソッドに使用チェックをつける
+		BOOST_FOREACH( const CMethod *pMethod, pParentClass->GetMethods() )
+		{
+			if( pMethod->IsVirtual() )
+			{
+				pMethod->GetUserProc().Using();
+			}
+		}
+
 		pCompilingMethod = pParentClass->GetMethods().GetMethodPtr( pUserProc );
 		if( !pCompilingMethod ){
Index: trunk/abdev/BasicCompiler_Common/src/Linker.cpp
===================================================================
--- trunk/abdev/BasicCompiler_Common/src/Linker.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/src/Linker.cpp	(revision 282)
@@ -102,4 +102,20 @@
 }
 
+void Linker::ResolveVtblSchedule( long dataSectionBaseOffset )
+{
+	BOOST_FOREACH( const Schedule &schedule, nativeCode.GetSchedules() )
+	{
+		if( schedule.GetType() == Schedule::Vtbl )
+		{
+			LONG_PTR vtblAddress = schedule.GetClass().GetVtblGlobalOffset();
+
+			nativeCode.Overwrite(
+				schedule.GetOffset(),
+				static_cast<long>( vtblAddress + imageBase + dataSectionBaseOffset )
+			);
+		}
+	}
+}
+
 void Linker::Link( ObjectModule &masterObjectModule )
 {
Index: trunk/abdev/BasicCompiler_Common/src/NativeCode.cpp
===================================================================
--- trunk/abdev/BasicCompiler_Common/src/NativeCode.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/src/NativeCode.cpp	(revision 282)
@@ -64,4 +64,12 @@
 }
 
+void NativeCode::PutVtblSchedule( const CClass *pClass )
+{
+	schedules.push_back( Schedule( pClass, size ) );
+
+	*((long *)(codeBuffer+size))=0;
+	size += sizeof(long);
+}
+
 void NativeCode::NextSourceLine()
 {
Index: trunk/abdev/BasicCompiler_Common/src/ObjectModule.cpp
===================================================================
--- trunk/abdev/BasicCompiler_Common/src/ObjectModule.cpp	(revision 281)
+++ trunk/abdev/BasicCompiler_Common/src/ObjectModule.cpp	(revision 282)
@@ -33,4 +33,8 @@
 		this->sources.push_back( source );
 	}
+
+	// TODO: basbufがいらなくなったら消す
+	extern char *basbuf;
+	basbuf = this->sources[0].GetBuffer();
 }
 
