#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; } 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 ); } } }