#include "stdafx.h" using namespace ActiveBasic::Compiler; int VtblGenerator::GenerateVTablePart( const Methods &methods ) { const UserProc **ppsi = (const UserProc **)malloc(methods.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()) { throw; } ppsi[i2]=&pMethod->GetUserProc(); i2++; } } int vtableDataTableOffset = compiler.GetObjectModule().dataTable.AddBinary( (void *)ppsi, methods.GetVtblNum()*sizeof(LONG_PTR) ); for( int i=0; i < methods.GetVtblNum(); i++ ) { pobj_Reloc->AddSchedule_DataSection(static_cast(vtableDataTableOffset+i*sizeof(LONG_PTR))); } free(ppsi); return vtableDataTableOffset; } void VtblGenerator::GenerateFullVTables( CClass &_class ) { if( _class.IsAbstract() ) { // 抽象クラスは無視 return; } if( !_class.IsUsing() ) { // 使われていないクラスは無視 return; } // vtblマスターリストの元データに不要なデータが含まれていたらエラー if( _class.vtblMasterList.size() ) { throw; } // 自身のクラスのvtblを生成 int thisClassVtblOffset = GenerateVTablePart( _class.GetDynamicMethods() ); _class.SetVtblOffset( thisClassVtblOffset ); _class.vtblMasterList.push_back( thisClassVtblOffset ); // インターフェイスのvtblを生成 BOOST_FOREACH( const ::Interface *pInterface, _class.GetInterfaces() ) { int tempVtblOffset = GenerateVTablePart( pInterface->GetDynamicMethods() ); _class.vtblMasterList.push_back( tempVtblOffset ); pInterface->SetVtblOffset( tempVtblOffset ); if( pInterface->GetClass().IsComInterface() ) { if( _class.GetComVtblOffset() ) { throw; } _class.SetComVtblOffset( tempVtblOffset ); } } // vtblマスターリストを生成 int offset = compiler.GetObjectModule().dataTable.AddBinary( (void *)&_class.vtblMasterList[0], static_cast(_class.vtblMasterList.size()*sizeof(LONG_PTR)) ); _class.SetVtblMasterListOffset( offset ); } void VtblGenerator::GenerateVTablesForAllClasses( Classes &classes ) { classes.Iterator_Reset(); while( classes.Iterator_HasNext() ) { CClass *pClass = classes.Iterator_GetNext(); GenerateFullVTables( *pClass ); // テンプレート展開されたクラスも BOOST_FOREACH( ActiveBasic::Common::Lexical::ExpandedTemplateClass *pExpandedTemplateClass, pClass->expandedTemplateClasses ) { if( !pExpandedTemplateClass->GetClass().expandedTemplateClasses.empty() ) { // テンプレート展開後のクラスが更にテンプレート展開されていることはありえない throw; } GenerateFullVTables( pExpandedTemplateClass->GetClass() ); } } } void VtblGenerator::ActionVtblSchedule( CClass &_class, LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection ) { if( _class.IsAbstract() ) { // 抽象クラスは無視 return; } if( !_class.IsUsing() ) { // 使われていないクラスは無視 return; } if( _class.GetVtblOffset() == -1 ) { return; } // 自身のクラスのvtbl { LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + _class.GetVtblOffset()); for( int i=0; i<_class.GetVtblNum(); i++ ){ const UserProc *pUserProc = (UserProc *)pVtbl[i]; if(!pUserProc) continue; if( pUserProc->GetBeginOpAddress() == 0 && pUserProc->GetEndOpAddress() == 0 ) { Jenga::Throw( "未解決の仮想関数が存在する" ); } pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection; } } // インターフェイスのvtbl BOOST_FOREACH( const ::Interface *pInterface, _class.GetInterfaces() ) { LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + pInterface->GetVtblOffset()); for( int i=0; iGetClass().GetVtblNum(); i++ ){ const UserProc *pUserProc = (UserProc *)pVtbl[i]; if(!pUserProc) continue; if( pUserProc->GetBeginOpAddress() == 0 && pUserProc->GetEndOpAddress() == 0 ) { Jenga::Throw( "未解決の仮想関数が存在する" ); } pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection; } } // vtblマスターリスト LONG_PTR *pVtblMasterList = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + _class.GetVtblMasterListOffset() ); for( int i=0; i(_class.vtblMasterList.size()); i++ ) { pVtblMasterList[i] = _class.vtblMasterList[i] + ImageBase + MemPos_DataSection; } } void VtblGenerator::ActionVtblScheduleForAllClasses( Classes &classes, LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection ) { classes.Iterator_Reset(); while( classes.Iterator_HasNext() ) { CClass *pClass = classes.Iterator_GetNext(); ActionVtblSchedule( *pClass, ImageBase, MemPos_CodeSection, MemPos_DataSection ); // テンプレート展開されたクラスも BOOST_FOREACH( ActiveBasic::Common::Lexical::ExpandedTemplateClass *pExpandedTemplateClass, pClass->expandedTemplateClasses ) { if( !pExpandedTemplateClass->GetClass().expandedTemplateClasses.empty() ) { // テンプレート展開後のクラスが更にテンプレート展開されていることはありえない throw; } ActionVtblSchedule( pExpandedTemplateClass->GetClass(), ImageBase, MemPos_CodeSection, MemPos_DataSection ); } } }