#include "../BasicCompiler_Common/common.h" #include "opcode.h" void _call_constructor( const CClass *pobj_c, const char *CreateParameter,int ObjectSize,BOOL bSomeObjects){ //////////////////////////// // コンストラクタの呼び出し //////////////////////////// //この関数を使用する場合は、 //・ebxにオブジェクトの個数 //・eaxに先頭ポインタ //をセットしておかなければならない int jnz_back; //jnzの番地 jnz_back=obp; if(bSomeObjects){ SetError(); //push ebx op_push(REG_EBX); } // ※ここでプッシュされた値はコンストラクタのthisポインタとなる //push eax op_push(REG_EAX); //////////////////////// // オーバーロードを解決 //////////////////////// std::vector subs; pobj_c->GetMethods().Enum( pobj_c->GetName().c_str(), subs ); UserProc *pUserProc; if( subs.size() > 0 ){ //オーバーロードを解決 pUserProc=OverloadSolutionWithStrParam(pobj_c->GetName().c_str(), subs,CreateParameter,""); if(!pUserProc) return; } //コンストラクタを呼び出す Opcode_CallProc(CreateParameter, pUserProc, PROCFLAG_NEW,"",0); { // 動的型情報をセットする // obj._System_SetType( _System_TypeBase.Search( strNamespace, name ) ) subs.clear(); pobj_c->GetMethods().Enum( "_System_SetType", subs ); if( subs.size() == 1 ){ char temporary[VN_SIZE]; sprintf( temporary, "_System_TypeBase.Search(\"\",\"%s\"))", pobj_c->GetName().c_str() ); Opcode_CallProc(temporary, subs[0], PROCFLAG_NEW,"",0); } else{ SetError(); } } //pop eax op_pop(REG_EAX); if(bSomeObjects){ //pop ebx op_pop(REG_EBX); //add eax,TypeSize OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=ObjectSize; obp+=sizeof(long); //sub ebx,1 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)0xEB; OpBuffer[obp++]=(char)0x01; //jnz ↑ OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0x85; *((long *)(OpBuffer+obp))=jnz_back-(obp+sizeof(long)); obp+=sizeof(long); } } void Operator_New( const CClass &classObj, const char *objectSizeStr, const char *parameter, const Type &baseType ){ int typeSize = classObj.GetSize(); if(classObj.IsAbstract()){ //抽象クラスだったとき SetError(125,classObj.GetName(),cp); } BOOL bSomeObjects=0; if(objectSizeStr[0]){ bSomeObjects=1; Type tempType; NumOpe(objectSizeStr,Type(),tempType); if( !tempType.IsWhole() ) SetError(49,NULL,cp); ChangeTypeToLong(tempType.GetBasicType()); //pop eax op_pop(REG_EAX); //※添え字上限値であることを考慮 //add eax,1 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)0xC0; OpBuffer[obp++]=(char)0x01; //オブジェクトの個数をebxに一時保持 //※ebxは関数が呼ばれても不変 //mov ebx,eax OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0xD8; //imul eax,size OpBuffer[obp++]=(char)0x69; OpBuffer[obp++]=(char)0xC0; *((long *)(OpBuffer+obp))=typeSize; obp+=sizeof(long); //add eax,OBJECT_HEAD_SIZE OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=OBJECT_HEAD_SIZE; obp+=sizeof(long); //push eax op_push(REG_EAX); } else{ //オブジェクトの個数をebxに一時保持 //※ebxは関数が呼ばれても不変 //mov ebx,1 OpBuffer[obp++]=(char)0xBB; *((long *)(OpBuffer+obp))=1; obp+=sizeof(long); //push size + OBJECT_HEAD_SIZE OpBuffer[obp++]=(char)0x68; *((long *)(OpBuffer+obp))=typeSize + OBJECT_HEAD_SIZE; obp+=sizeof(long); } if( baseType.IsObject() ){ // オブジェクト インスタンス // ※DeleteはGCで処理 //call _System_GC_malloc_ForObject extern UserProc *pSub_System_GC_malloc_ForObject; op_call(pSub_System_GC_malloc_ForObject); } else{ // オブジェクトポインタ // ※明示的なDeleteが必要 //call _System_GC_malloc_ForObjectPtr extern UserProc *pSub_System_GC_malloc_ForObjectPtr; op_call(pSub_System_GC_malloc_ForObjectPtr); } /* 確保されたヒープ領域のポインタ(callocの戻り値eax)をpPtrとすると、 pPtr[0]=オブジェクトの個数 pPtr[1]=オブジェクトのサイズ pPtr[2]=デストラクタの関数ポインタ pPtr[3]=reserve */ //mov dword ptr[eax],ebx(オブジェクトの個数) OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x18; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); //mov ecx,TypeSize OpBuffer[obp++]=(char)0xB9; *((long *)(OpBuffer+obp))=typeSize; obp+=sizeof(long); //mov dword ptr[eax],ecx(オブジェクトのサイズ) OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x08; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); const CMethod *method = classObj.GetDestructorMethod(); if( method == NULL ) return; //mov ecx,DestructorProcAddr OpBuffer[obp++]=(char)0xB9; pobj_SubAddrSchedule->add(method->pUserProc,0); method->pUserProc->Using(); obp+=sizeof(long); //mov dword ptr[eax],ecx(デストラクタの関数ポインタ) OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x08; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); // リザーブ領域 //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); // ※ここでプッシュされた値はNew演算子の戻り値となる //push eax op_push(REG_EAX); ///////////////////////////////////////////////////////////////////// //////////////////////////// // コンストラクタの呼び出し //////////////////////////// _call_constructor(&classObj,parameter,typeSize,bSomeObjects); } void OpcodeDelete(const char *Parameter, bool isSweeping){ Type tempType; if( !NumOpe(Parameter,Type(),tempType) ){ return; } if(!( tempType.IsObjectPtr() || tempType.IsVoidPtr() )) SetError(122,NULL,cp); //pop eax op_pop(REG_EAX); //sub eax,sizeof(DWORD)*3 op_sub_RV8( REG_EAX, OBJECT_HEAD_SIZE ); //push eax op_push(REG_EAX); //mov ebx,dword ptr[eax](オブジェクトの個数) OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x18; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); //mov esi,dword ptr[eax](オブジェクトのサイズ) OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x30; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); //mov edx,dword ptr[eax](デストラクタの関数ポインタ) OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x10; //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); // リザーブ領域 //add eax,sizeof(DWORD) OpBuffer[obp++]=(char)0x05; *((long *)(OpBuffer+obp))=sizeof(DWORD); obp+=sizeof(long); //mov ecx,eax OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0xC8; //jnzの番地 int jnz_back; jnz_back=obp; //push ecx op_push(REG_ECX); //push edx op_push(REG_EDX); //push ecx(Thisポインタ ※隠れた第一パラメータ) op_push(REG_ECX); //call edx OpBuffer[obp++]=(char)0xFF; OpBuffer[obp++]=(char)0xD2; //pop edx op_pop(REG_EDX); //pop ecx op_pop(REG_ECX); //add ecx,esi OpBuffer[obp++]=(char)0x03; OpBuffer[obp++]=(char)0xCE; //sub ebx,1 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)0xEB; OpBuffer[obp++]=(char)0x01; //jnz ↑ OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0x85; *((long *)(OpBuffer+obp))=jnz_back-(obp+sizeof(long)); obp+=sizeof(long); ////////////////////////////////////////// // オブジェクトメンバ変数用のメモリを解放 ////////////////////////////////////////// if( isSweeping ){ //call _System_GC_free_for_SweepingDelete extern UserProc *pSub_System_GC_free_for_SweepingDelete; op_call(pSub_System_GC_free_for_SweepingDelete); } else{ //call free extern UserProc *pSub_free; op_call(pSub_free); } }