#include "stdafx.h" #include #include "../BasicCompiler_Common/common.h" #include "opcode.h" void _call_constructor( const CClass *pobj_c, const char *CreateParameter,int ObjectSize,BOOL bSomeObjects){ //////////////////////////// // コンストラクタの呼び出し //////////////////////////// //この関数を使用する場合は、 //・ebxにオブジェクトの個数 //・eaxに先頭ポインタ //をセットしておかなければならない /* //jnzのジャンプ先番地 extern int obp; int jnz_back = obp;*/ if(bSomeObjects){ compiler.errorMessenger.OutputFatalError(); //push ebx //compiler.codeGenerator.op_push(REG_EBX); } // ※ここでプッシュされた値はコンストラクタのthisポインタとなる //push eax compiler.codeGenerator.op_push(REG_EAX); //////////////////////// // オーバーロードを解決 //////////////////////// std::vector subs; pobj_c->GetDynamicMethods().Enum( pobj_c->GetName().c_str(), subs ); const UserProc *pUserProc; if( subs.size() > 0 ){ //オーバーロードを解決 pUserProc=OverloadSolutionWithStrParam(pobj_c->GetName().c_str(), subs,CreateParameter,""); if(!pUserProc) return; } { // 動的型情報をセットする // obj._System_SetType( _System_TypeBase_Search( fullName ) ) subs.clear(); pobj_c->GetDynamicMethods().Enum( "_System_SetType", subs ); if( subs.size() == 1 ){ char temporary[VN_SIZE]; sprintf( temporary, "_System_TypeBase_Search(\"%s\"))", pobj_c->GetFullName().c_str() ); Opcode_CallProc(temporary, subs[0], PROCFLAG_NEW,""); } else{ compiler.errorMessenger.OutputFatalError(); } // インターフェイスを初期化する // TODO: 実装 } //コンストラクタを呼び出す Opcode_CallProc(CreateParameter, pUserProc, PROCFLAG_NEW | PROCFLAG_PERMIT_CONSTRUCTOR,""); //pop eax compiler.codeGenerator.op_pop(REG_EAX); if(bSomeObjects){ /* //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //add eax,TypeSize compiler.codeGenerator.op_add_RV( REG_EAX, ObjectSize ); //sub ebx,1 compiler.codeGenerator.op_sub_RV8(REG_EBX,1); //jne ↑ compiler.codeGenerator.op_jne( jnz_back-obp, sizeof(long), false, true ); */ } } void Operator_New( const CClass &objClass, const char *objectSizeStr, const char *parameter, const Type &baseType ) { const CClass *pClass = &objClass; if( pClass->IsInterface() ) { pClass = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr(); } int typeSize = pClass->GetSize(); if(pClass->IsAbstract()) { std::string tempMessage; foreach( const CMethod *pMethod, pClass->GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ if( !tempMessage.empty() ) { tempMessage += ", "; } tempMessage += pMethod->GetUserProc().GetName(); } } } // インターフェイスのvtbl foreach( const ::Interface *pInterface, pClass->GetInterfaces() ) { foreach( const CMethod *pMethod, pInterface->GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ if( !tempMessage.empty() ) { tempMessage += ", "; } tempMessage += pMethod->GetUserProc().GetName(); } } } } //抽象クラスだったとき compiler.errorMessenger.Output(-1,"\"%s\" は抽象クラスです。インスタンス化することはできません(抽象メソッド … " + tempMessage + ")。",cp); } BOOL bSomeObjects=0; if(objectSizeStr[0]){ bSomeObjects=1; Type tempType; NumOpe(objectSizeStr,Type(),tempType); if( !tempType.IsWhole() ) compiler.errorMessenger.Output(49,NULL,cp); ChangeTypeToLong(tempType.GetBasicType()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //※添え字上限値であることを考慮 //inc eax compiler.codeGenerator.op_inc( REG_EAX ); //オブジェクトの個数をebxに一時保持 //※ebxは関数が呼ばれても不変 //mov ebx,eax compiler.codeGenerator.op_mov_RR( REG_EBX, REG_EAX ); //imul eax,size compiler.codeGenerator.op_imul_RV( REG_EAX, typeSize ); //add eax,OBJECT_HEAD_SIZE compiler.codeGenerator.op_add_RV8( REG_EAX, (char)OBJECT_HEAD_SIZE ); //push eax compiler.codeGenerator.op_push(REG_EAX); } else{ //オブジェクトの個数をebxに一時保持 //※ebxは関数が呼ばれても不変 //mov ebx,1 compiler.codeGenerator.op_mov_RV( REG_EBX, 1 ); //push size + OBJECT_HEAD_SIZE compiler.codeGenerator.op_push_V( typeSize + OBJECT_HEAD_SIZE ); } if( baseType.IsObject() ){ // オブジェクト インスタンス // ※DeleteはGCで処理 //call _System_GC_malloc_ForObject extern const UserProc *pSub_System_GC_malloc_ForObject; compiler.codeGenerator.op_call(pSub_System_GC_malloc_ForObject); } else{ // オブジェクトポインタ // ※明示的なDeleteが必要 //call _System_GC_malloc_ForObjectPtr extern const UserProc *pSub_System_GC_malloc_ForObjectPtr; compiler.codeGenerator.op_call(pSub_System_GC_malloc_ForObjectPtr); } /* 確保されたヒープ領域のポインタ(callocの戻り値eax)をpPtrとすると、 pPtr[0]=オブジェクトの個数 pPtr[1]=オブジェクトのサイズ pPtr[2]=デストラクタの関数ポインタ pPtr[3]=reserve */ //mov dword ptr[eax],ebx(オブジェクトの個数) compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); //mov ecx,TypeSize compiler.codeGenerator.op_mov_RV( REG_ECX, typeSize ); //mov dword ptr[eax],ecx(オブジェクトのサイズ) compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); const CMethod *method = pClass->GetDestructorMethod(); if( method == NULL ) return; //mov ecx,DestructorProcAddr compiler.codeGenerator.op_addressof( REG_ECX, &method->GetUserProc() ); //mov dword ptr[eax],ecx(デストラクタの関数ポインタ) compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); // リザーブ領域 //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); //仮想関数テーブルを初期化 if( pClass->IsExistVirtualFunctions() && !pClass->IsAbstract() ) { // mov ecx,com_vtbl compiler.codeGenerator.op_mov_RV_com_vtbl( REG_ECX, pClass ); //mov dword ptr[eax],ecx compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE ); // mov rcx,vtblAddress compiler.codeGenerator.op_mov_RV_vtbl( REG_ECX, pClass ); //mov qword ptr[rax+sizeof(com_vtbl)],rcx compiler.codeGenerator.op_mov_MR(sizeof(long),REG_ECX,REG_EAX,PTR_SIZE,MOD_BASE_DISP8); // 仮想関数になるメソッドに使用チェックをつける foreach( const CMethod *pMethod, pClass->GetDynamicMethods() ) { if( pMethod->IsVirtual() ) { pMethod->GetUserProc().Using(); } } foreach( const ::Interface *pInterface, pClass->GetInterfaces() ) { foreach( const CMethod *pMethod, pInterface->GetDynamicMethods() ) { if( pMethod->IsVirtual() ) { pMethod->GetUserProc().Using(); } } } } // ※ここでプッシュされた値はNew演算子の戻り値となる //push eax compiler.codeGenerator.op_push(REG_EAX); ///////////////////////////////////////////////////////////////////// //////////////////////////// // コンストラクタの呼び出し //////////////////////////// _call_constructor(pClass,parameter,typeSize,bSomeObjects); } void OpcodeDelete(const char *Parameter, bool isSweeping){ Type tempType; if( !NumOpe(Parameter,Type(),tempType) ){ return; } if(!( tempType.IsObjectPtr() || tempType.IsVoidPtr() )) compiler.errorMessenger.Output(122,NULL,cp); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //sub eax,sizeof(DWORD)*3 compiler.codeGenerator.op_sub_RV8( REG_EAX, OBJECT_HEAD_SIZE ); //push eax compiler.codeGenerator.op_push(REG_EAX); //mov ebx,dword ptr[eax](オブジェクトの個数) compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); //mov esi,dword ptr[eax](オブジェクトのサイズ) compiler.codeGenerator.op_mov_RM( sizeof(long), REG_ESI, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); //mov edx,dword ptr[eax](デストラクタの関数ポインタ) compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EDX, REG_EAX, 0, MOD_BASE ); //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); // リザーブ領域 //add eax,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) ); //mov ecx,eax compiler.codeGenerator.op_mov_RR( REG_ECX, REG_EAX ); //jnzの番地 /*extern int obp; int jnz_back = obp;*/ //push ecx compiler.codeGenerator.op_push(REG_ECX); //push edx compiler.codeGenerator.op_push(REG_EDX); //push ecx(Thisポインタ ※隠れた第一パラメータ) compiler.codeGenerator.op_push(REG_ECX); //call edx compiler.codeGenerator.op_call_R( REG_EDX ); //pop edx compiler.codeGenerator.op_pop(REG_EDX); //pop ecx compiler.codeGenerator.op_pop(REG_ECX); //add ecx,esi compiler.codeGenerator.op_add_RR( REG_ECX, REG_ESI ); //sub ebx,1 compiler.codeGenerator.op_sub_RV8(REG_EBX,1); //jne ↑ //compiler.codeGenerator.op_jne( jnz_back-obp, sizeof(long), false, true ); ////////////////////////////////////////// // オブジェクトメンバ変数用のメモリを解放 ////////////////////////////////////////// if( isSweeping ){ //call _System_GC_free_for_SweepingDelete extern const UserProc *pSub_System_GC_free_for_SweepingDelete; compiler.codeGenerator.op_call(pSub_System_GC_free_for_SweepingDelete); } else{ //call free extern const UserProc *pSub_free; compiler.codeGenerator.op_call(pSub_free); } }