#include "stdafx.h" #include #include #include #include "../common.h" #ifdef _AMD64_ #include "../../compiler_x64/opcode.h" #else #include "../../compiler_x86/opcode.h" #endif using namespace ActiveBasic::Compiler; void CClass::Using() const { if( this->IsUsing() ) { // 既に使用することになっている return; } Prototype::Using(); // 仮想関数になるメソッドに使用チェックをつける const CClass &objThis = *this; BOOST_FOREACH( const CMethod *pMethod, objThis.GetDynamicMethods() ) { if( pMethod->IsVirtual() ) { pMethod->GetUserProc().Using(); } } } bool CClass::IsClass() const { return classType == CClass::Class; } bool CClass::IsInterface() const { return classType == CClass::Interface; } bool CClass::IsComInterface() const { return classType == CClass::ComInterface; } bool CClass::IsEnum() const { return classType == CClass::Enum; } bool CClass::IsDelegate() const { return classType == CClass::Delegate; } bool CClass::IsStructure() const { return classType == CClass::Structure; } // コンストラクタのコンパイルを開始 void CClass::NotifyStartConstructorCompile() const { isCompilingConstructor = true; } //コンストラクタのコンパイルを終了 void CClass::NotifyFinishConstructorCompile() const { isCompilingConstructor = false; } //コンストラクタをコンパイル中かどうかを判別 bool CClass::IsCompilingConstructor() const { return isCompilingConstructor; } //デストラクタのコンパイルを開始 void CClass::NotifyStartDestructorCompile() const{ isCompilingDestructor = true; } //デストラクタのコンパイルを終了 void CClass::NotifyFinishDestructorCompile() const{ isCompilingDestructor = false; } //デストラクタをコンパイル中かどうかを判別 bool CClass::IsCompilingDestructor() const { return isCompilingDestructor; } //自身の派生クラスかどうかを確認 bool CClass::IsSubClass( const CClass *pSubClass ) const { if( !pSubClass->HasSuperClass() ) { return false; } const CClass *pTempClass = &pSubClass->GetSuperClass(); while( pTempClass ){ if( this == pTempClass ) return true; pTempClass = &pTempClass->GetSuperClass(); } return false; } //自身と等しいまたは派生クラスかどうかを確認 bool CClass::IsEqualsOrSubClass( const CClass *pSubClass ) const { if( IsEquals( pSubClass ) ) return true; return IsSubClass( pSubClass ); } // 自身と等しいまたは派生クラス、基底クラスかどうかを確認 bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const { if( IsEquals( &objClass ) ) return true; if( IsSubClass( &objClass ) ) return true; if( objClass.IsSubClass( this ) ) return true; return false; } bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const { BOOST_FOREACH( const ::Interface *pInterface, interfaces ){ if( pInterfaceClass == &pInterface->GetClass() ){ return true; } } return false; } bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine ) { //メソッドをコピー BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){ CMethod *pMethod = new DynamicMethod( *pBaseMethod ); // アクセシビリティ if(pBaseMethod->GetAccessibility() == Prototype::Private){ pMethod->SetAccessibility( Prototype::None ); } else{ pMethod->SetAccessibility( pBaseMethod->GetAccessibility() ); } //pobj_Inherits // ※継承元のClassIndexをセット(入れ子継承を考慮する) if(pBaseMethod->GetInheritsClassPtr()==0){ pMethod->SetInheritsClassPtr( &inheritsClass ); } else{ pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() ); } GetDynamicMethods().push_back( pMethod ); } //仮想関数の数 AddVtblNum( inheritsClass.GetVtblNum() ); //継承先のクラスをメンバとして保持する SetSuperClass( &inheritsClass ); SetSuperClassActualTypeParameters( actualTypeParameters ); // インターフェイスを引き継ぐ BOOST_FOREACH( ::Interface *pInterface, inheritsClass.GetInterfaces() ) { interfaces.push_back( new ::Interface( *pInterface ) ); } if( this->IsInterface() && inheritsClass.IsComInterface() ) { // COMインターフェイスを継承した場合はCOMインターフェイスにする this->SetClassType( CClass::ComInterface ); } return true; } void CClass::AddDynamicMember( Member *pMember ) { dynamicMembers.push_back( pMember ); } void CClass::AddStaticMember( Member *pMember ) { staticMembers.push_back( pMember ); } bool CClass::DupliCheckAll(const char *name) const { //重複チェック //メンバ if(DupliCheckMember(name)) return 1; //メソッド BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){ return 1; } } return 0; } bool CClass::DupliCheckMember(const char *name) const { //重複チェック if( this->HasSuperClass() ) { if( this->GetSuperClass().DupliCheckMember( name ) ) { // 基底クラスで重複が発見された return true; } } // 動的メンバ BOOST_FOREACH( Member *pMember, dynamicMembers ) { if( GetName() == pMember->GetName() ) { return true; } } // 静的メンバ BOOST_FOREACH( Member *pMember, staticMembers ){ if( GetName() == pMember->GetName() ){ return true; } } return false; } const Member *CClass::FindDynamicMember( const char *memberName ) const { if( this->HasSuperClass() ) { // 基底クラスで検索 const Member *result = this->GetSuperClass().FindDynamicMember( memberName ); if( result ) { return result; } } BOOST_FOREACH( Member *pMember, GetDynamicMembers() ) { if( pMember->GetName() == memberName ) { return pMember; } } return NULL; } void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector &subs ) const { // 動的メソッド GetDynamicMethods().Enum( methodName, subs ); // インターフェイス メソッド BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() ) { pInterface->GetDynamicMethods().Enum( methodName, subs ); } } const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const { // 動的メソッド const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc ); if( !result ) { // インターフェイス メソッド BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() ) { result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc ); if( result ) { return result; } } } return result; } //サイズを取得 int CClass::GetSize() const { int resultSize = 0; int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 alignment = this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { // 基底クラスのサイズを追加 resultSize += this->GetSuperClass().GetSize(); // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { // メンバサイズ int tempMemberSize = pMember->GetType().GetSize(); // 一時アラインメントを算出 int tempAlignment = tempMemberSize; if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } // アラインメントを考慮してパディングを追加 if( GetFixedAlignment() && alignment < tempAlignment ) { if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } else { if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } if( tempMemberSize == 0 ) { if( !pMember->GetType().IsStruct() ) { throw; } //メンバを持たない構造体 //※何もしない(オフセットの計算をしない) } else{ if( resultSize % tempAlignment ) { resultSize += tempAlignment - ( resultSize % tempAlignment ); } } } // メンバサイズを加算(配列を考慮) resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() ); } if( alignment ) { // 末尾アラインメントを考慮してパディングを追加 if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } return resultSize; } //メンバのオフセットを取得 int CClass::GetMemberOffset( const char *memberName ) const { int resultSize = 0; int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 alignment = this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { if( this->GetSuperClass().HasDynamicMember( memberName ) ) { // 基底クラスのメンバを取得 return this->GetSuperClass().GetMemberOffset( memberName ); } // 基底クラスのサイズを追加 resultSize += this->GetSuperClass().GetSize(); // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { // メンバサイズ int tempMemberSize = pMember->GetType().GetSize(); // 一時アラインメントを算出 int tempAlignment = tempMemberSize; if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } // アラインメントを考慮してパディングを追加 if( GetFixedAlignment() && alignment < tempAlignment ) { if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } else { if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } if( tempMemberSize == 0 ) { if( !pMember->GetType().IsStruct() ) { throw; } //メンバを持たない構造体 //※何もしない(オフセットの計算をしない) } else{ if( resultSize % tempAlignment ) { resultSize += tempAlignment - ( resultSize % tempAlignment ); } } } if(memberName){ //メンバ指定がある場合は、オフセットを返す if( pMember->GetName() == memberName ) { return resultSize; } } // メンバサイズを加算(配列を考慮) resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() ); } if( alignment ) { // 末尾アラインメントを考慮してパディングを追加 if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } return resultSize; } int CClass::GetAlignment() const { int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 return this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 alignment = PTR_SIZE; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { int tempAlignment = pMember->GetType().GetSize(); if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } } return alignment; } void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const { vtblMasterListIndex = 0; vtblIndex = 0; BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if( &pMethod->GetUserProc() == pUserProc ) { return; } if( pMethod->IsVirtual() ) { vtblIndex++; } } BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { vtblMasterListIndex++; vtblIndex = 0; BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){ if( &pMethod->GetUserProc() == pUserProc ) { return; } if( pMethod->IsVirtual() ) { vtblIndex++; } } } throw; } int CClass::GetVtblMasterListIndex( const CClass *pClass ) const { int result = 0; BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { result++; if( &pInterface->GetClass() == pClass ) { return result; } } throw; } long CClass::GetVtblMasterListOffset() const { if( vtblMasterListOffset == -1 ) { throw; } return vtblMasterListOffset; } bool CClass::IsAbstract() const { // 未実装(abstract)の仮想関数を持つ場合はtrueを返す BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ return true; } } } // インターフェイスのvtbl BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ return true; } } } } return false; } void Classes::InitStaticMember(){ //静的メンバをグローバル領域に作成 //イテレータをリセット extern int cp; int back_cp=cp; this->Iterator_Reset(); while(this->Iterator_HasNext()){ CClass &objClass = *this->Iterator_GetNext(); if( objClass.isTargetObjectModule == false ) { // 静的リンクライブラリの場合は飛ばす(既にインスタンスが定義済みであるため) continue; } // 名前空間をセット compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = objClass.GetNamespaceScopes(); DWORD dwFlags = 0; if( objClass.GetName() == "_System_TypeBase" ) { // _System_TypeBaseクラスはグローバル、スタティック領域を初期化するためのクラスなのでここでの初期化は除外する dwFlags |= DIMFLAG_NONCALL_CONSTRACTOR; } // コンパイル中クラスとしてセット compiler.SetCompilingClass( &objClass ); const EnumInfo *pEnumInfo = NULL; if( objClass.IsEnum() ) { pEnumInfo = compiler.enumInfoCollection.Find( objClass ); } int i=0; BOOST_FOREACH( Member *member, objClass.GetStaticMembers() ) { if( pEnumInfo ) { cp = pEnumInfo->GetEnumMember( member->GetName() ).GetSourceIndex(); } char temporary[VN_SIZE]; sprintf(temporary,"%s.%s",objClass.GetName().c_str(),member->GetName().c_str()); dim( temporary, member->GetSubscripts(), member->GetType(), member->GetInitializeExpression().c_str(), member->GetConstructParameter().c_str(), dwFlags); i++; } compiler.SetCompilingClass( NULL ); } compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().clear(); cp=back_cp; } void Classes::Compile_System_InitializeUserTypes(){ char temporary[VN_SIZE]; //////////////////////////////////////////////////////////////////// // クラス登録 //////////////////////////////////////////////////////////////////// // イテレータをリセット Iterator_Reset(); while( Iterator_HasNext() ){ const CClass &objClass = *Iterator_GetNext(); if( !objClass.IsUsing() ){ // 未使用のクラスは無視する continue; } std::string referenceOffsetsBuffer; int numOfReference = 0; objClass.GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference ); sprintf( temporary , "Add(%c%c_System_TypeForClass[strNamespace=\"%s\",name=\"%s\",fullName=\"%s\",referenceOffsets=[%s],numOfReference=%d])" , 1 , ESC_SYSTEM_STATIC_NEW , objClass.GetNamespaceScopes().ToString().c_str() // 名前空間 , objClass.GetName().c_str() // クラス名 , objClass.GetFullName().c_str() // フルネーム , referenceOffsetsBuffer.c_str() // 参照メンバオフセット配列 , numOfReference // 参照メンバの個数 ); // コンパイル ChangeOpcode( temporary ); objClass.SetTypeInfoDataTableOffset( compiler.GetObjectModule().dataTable.GetLastMadeConstObjectDataTableOffset() ); } } void Classes::Compile_System_InitializeUserTypesForBaseType() { extern int cp; cp = -1; //////////////////////////////////////////////////////////////////// // 基底クラスを登録 //////////////////////////////////////////////////////////////////// char temporary[8192]; sprintf(temporary, "%c%ctempType=Nothing%c%c_System_TypeForClass" , HIBYTE( COM_DIM ) , LOBYTE( COM_DIM ) , 1 , ESC_AS ); ChangeOpcode( temporary ); // イテレータをリセット Iterator_Reset(); while( Iterator_HasNext() ){ const CClass &objClass = *Iterator_GetNext(); if( !objClass.IsUsing() ){ // 未使用のクラスは無視する continue; } if( objClass.HasSuperClass() || objClass.GetDynamicMembers().size() ){ sprintf( temporary , "tempType=Search(\"%s\") As ActiveBasic.Core._System_TypeForClass" , objClass.GetFullName().c_str() ); // コンパイル MakeMiddleCode( temporary ); ChangeOpcode( temporary ); sprintf( temporary , "tempType.SetClassInfo(%d,_System_GetComVtbl(%s),_System_GetVtblList(%s),_System_GetDefaultConstructor(%s),_System_GetDestructor(%s))" , objClass.GetSize() , objClass.GetFullName().c_str() , objClass.GetFullName().c_str() , objClass.GetFullName().c_str() , objClass.GetFullName().c_str() , objClass.GetName().c_str() ); // コンパイル ChangeOpcode( temporary ); if( objClass.HasSuperClass() ) { sprintf( temporary , "tempType.SetBaseType(Search(\"%s\"))" , objClass.GetSuperClass().GetFullName().c_str() ); // コンパイル ChangeOpcode( temporary ); } if( objClass.GetDynamicMembers().size() ) { // メンバの型を示すTypeInfoオブジェクトへのDataOffset配列の静的データ定義文字列を取得 sprintf( temporary, "tempType.SetMembers([%s],[%s],[%s],%d)", objClass.GetStaticDefiningStringAsMemberNames().c_str(), objClass.GetStaticDefiningStringAsMemberTypeInfoNames().c_str(), objClass.GetStaticDefiningStringAsMemberOffsets().c_str(), objClass.GetDynamicMembers().size() ); ChangeOpcode( temporary ); } } } } const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const std::string &name ) const { if( namespaceScopes.size() == 0 && name == "Object" ){ return GetObjectClassPtr(); } else if( namespaceScopes.size() == 0 && name == "String" ){ return GetStringClassPtr(); } std::vector classes; const CClass *pClass = GetHashArrayElement( name.c_str() ); while( pClass ) { if( pClass->IsEqualSymbol( namespaceScopes, name ) ){ //名前空間とクラス名が一致した classes.push_back( pClass ); } pClass = pClass->GetChainNext(); } if( classes.size() > 0 ) { // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする pClass = classes.front(); BOOST_FOREACH( const CClass *pTempClass, classes ) { if( pClass->GetNamespaceScopes().size() < pTempClass->GetNamespaceScopes().size() ) { pClass = pTempClass; } } return pClass; } // TypeDefも見る int index = compiler.GetObjectModule().meta.GetTypeDefs().GetIndex( namespaceScopes, name ); if( index != -1 ){ Type type = compiler.GetObjectModule().meta.GetTypeDefs()[index].GetBaseType(); if( type.IsObject() ){ return &type.GetClass(); } } return NULL; } const CClass *Classes::Find( const std::string &fullName ) const { char AreaName[VN_SIZE] = ""; //オブジェクト変数 char NestName[VN_SIZE] = ""; //入れ子メンバ bool isNest = SplitMemberName( fullName.c_str(), AreaName, NestName ); return Find( NamespaceScopes( AreaName ), NestName ); } const CClass *Classes::GetStringClassPtr() const { if( !pStringClass ){ // キャッシュしておく pStringClass = this->Find( NamespaceScopes( "System" ), "String" ); if( !pStringClass ) { compiler.errorMessenger.Output(400, "System.String", cp); static CClass dummy; return &dummy; } return pStringClass; } return pStringClass; } const CClass *Classes::GetObjectClassPtr() const { if( !pObjectClass ){ // キャッシュしておく pObjectClass = this->Find( NamespaceScopes( "System" ), "Object" ); if( !pObjectClass ) { compiler.errorMessenger.Output(400, "System.Object", cp); static CClass dummy; return &dummy; } return pObjectClass; } return pObjectClass; } const CClass *Classes::GetInterfaceInfoClassPtr() const { if( !pInterfaceInfo ){ // キャッシュしておく pInterfaceInfo = this->Find( "ActiveBasic.Core.InterfaceInfo" ); if( !pInterfaceInfo ) { compiler.errorMessenger.Output(400, "ActiveBasic.Core.InterfaceInfo", cp); static CClass dummy; return &dummy; } return pInterfaceInfo; } return pInterfaceInfo; } std::string CClass::GetStaticDefiningStringAsMemberNames() const { std::string result; BOOST_FOREACH( const Member *pMember, dynamicMembers ) { if( result.size() ) { result += ","; } result += "\"" + pMember->GetName() + "\""; } return result; } std::string CClass::GetStaticDefiningStringAsMemberTypeInfoNames() const { std::string result; BOOST_FOREACH( const Member *pMember, dynamicMembers ) { if( result.size() ) { result += ","; } result += "\"" + compiler.TypeToString( pMember->GetType() ) + "\""; } return result; } std::string CClass::GetStaticDefiningStringAsMemberOffsets() const { std::string result; BOOST_FOREACH( const Member *pMember, dynamicMembers ) { if( result.size() ) { result += ","; } int offset = this->GetMemberOffset( pMember->GetName().c_str() ); char temporary[255]; itoa( offset, temporary, 16 ); result += (std::string)"&H" + temporary; } return result; } void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const { const CClass &thisClass = *this; BOOST_FOREACH( const Member *pMember, thisClass.GetDynamicMembers() ) { if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() ) { if( referenceOffsetsBuffer.size() ) { referenceOffsetsBuffer += ","; } char temp[255]; sprintf( temp, "%d", baseOffset + thisClass.GetMemberOffset( pMember->GetName().c_str() ) ); referenceOffsetsBuffer += temp; numOfReference++; } if( pMember->GetType().IsStruct() && !pMember->GetType().IsPointer() ) { // 構造体の実体をメンバに持つとき int baseOffset = thisClass.GetMemberOffset( pMember->GetName().c_str() ); // 構造体メンバでGCによるチェックが必要な参照位置を追加 pMember->GetType().GetClass().GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference, baseOffset ); } } }