#include "../BasicCompiler_Common/common.h" #include "Opcode.h" void FreeTempObject(int reg,CClass *pobj_c){ if(!IsSafeReg(reg)) SetError(300,NULL,cp); CMethod *method = pobj_c->GetDestructorMethod(); if( method ){ //push reg op_push(reg); //call DestructorProcAddr op_call( method->psi ); } //push reg op_push(reg); //call free extern SUBINFO *pSub_free; op_call(pSub_free); } int CallOperatorProc(int idCalc,TYPEINFO *pBaseTypeInfo,int *type,LONG_PTR *index_stack,BOOL *bUseHeap,int &sp){ //オーバーロードされたオペレータ関数を呼び出す CClass *pobj_c; pobj_c=(CClass *)index_stack[sp-2]; std::vector subs; pobj_c->EnumMethod( idCalc, subs ); if( subs.size() == 0 ){ return 0; } //項の数 BOOL bTwoTerm=1; if(idCalc==CALC_AS) bTwoTerm=0; int i; BOOL bReturnTypeIsObject=1; TYPEINFO ReturnType={DEF_OBJECT,subs[0]->u.ReturnIndex}; foreach( SUBINFO *psi, subs ){ if(psi->ReturnType!=DEF_OBJECT) bReturnTypeIsObject=0; } if(bReturnTypeIsObject==0){ if(pBaseTypeInfo){ if(pBaseTypeInfo->type==DEF_OBJECT){ ReturnType.u.lpIndex=pBaseTypeInfo->u.lpIndex; } } } ///////////////////////////////////////////// // オーバーロード解決用のパラメータを設定 ///////////////////////////////////////////// PARAMETER_INFO *ppi = (PARAMETER_INFO *)HeapAlloc(hHeap,0,sizeof(PARAMETER_INFO)*3); int iParmNum=0; if(bTwoTerm){ ppi[iParmNum].bArray=0; ppi[iParmNum].bByVal=0; ppi[iParmNum].name=0; ppi[iParmNum].type=type[sp-1]; ppi[iParmNum].u.index=index_stack[sp-1]; ppi[iParmNum].SubScripts[0]=-1; iParmNum++; } //オーバーロードを解決 char temporary[255]; if(idCalc==CALC_EQUAL) lstrcpy(temporary,"=="); else GetCalcName(idCalc,temporary); SUBINFO *psi; psi=OverloadSolution(temporary,subs,ppi,iParmNum,pBaseTypeInfo); if(!psi){ HeapDefaultFree(ppi); return -1; } else{ //オーバーロードされていないが、パラメータ個数が一致しないとき if(iParmNum!=psi->ParmNum){ HeapDefaultFree(ppi); return -1; } } for(i=0;ipParmInfo[i].type, psi->pParmInfo[i].u.index, ppi[i].type, ppi[i].u.index, "", i); } HeapDefaultFree(ppi); int right_side_size = GetTypeSize(type[sp-1],index_stack[sp-1]); if(bTwoTerm){ if(psi->pRealParmInfo[1].type==DEF_STRUCT&&psi->pRealParmInfo[1].bByVal){ //一時オブジェクトはメソッド内で破棄される bUseHeap[sp-1]=0; } } if(psi->ReturnType==DEF_STRUCT){ ////////////////////////////////////////////////////// // 戻り値に構造体インスタンスを持つ場合 // ※ByRef _System_ReturnValue パラメータ用領域を取得 ////////////////////////////////////////////////////// int object_size = psi->u.Return_pobj_c->GetSize(); //push object_size op_push_value(object_size); //call calloc extern SUBINFO *pSub_calloc; op_call(pSub_calloc); //mov ebx,eax op_mov_RR(REG_EBX,REG_EAX); } //2つの項を取り出す if(bTwoTerm){ if(right_side_size==sizeof(_int64)){ //pop eax op_pop(REG_EAX); //pop edx op_pop(REG_EDX); } else{ //pop eax op_pop(REG_EAX); } } //pop ecx op_pop(REG_ECX); //ヒープ解放用に退避 if(bUseHeap[sp-1]){ //mov esi,eax op_mov_RR(REG_ESI,REG_EAX); } if(bUseHeap[sp-2]){ //mov edi,ecx op_mov_RR(REG_EDI,REG_ECX); } if(bTwoTerm){ if(right_side_size==sizeof(_int64)){ //push edx op_push(REG_EDX); //push eax op_push(REG_EAX); } else{ //push eax op_push(REG_EAX); } if( !psi->pRealParmInfo[1].bByVal ){ //一時参照を作成 //mov eax,esp op_mov_RR( REG_EAX, REG_ESP ); //push eax op_push( REG_EAX ); } } if(psi->ReturnType==DEF_STRUCT){ //push ebx op_push(REG_EBX); } //push ecx op_push(REG_ECX); //call operator_proc op_call(psi); if(bTwoTerm){ if( !psi->pRealParmInfo[1].bByVal ){ //一時参照を破棄 op_pop( REG_NON ); } } if(psi->ReturnType!=DEF_NON){ //スタックへプッシュ PushReturnValue(psi->ReturnType); } if(bUseHeap[sp-1]){ FreeTempObject(REG_ESI,(CClass *)index_stack[sp-1]); } if(bUseHeap[sp-2]){ FreeTempObject(REG_EDI,(CClass *)index_stack[sp-2]); } sp--; type[sp-1]=psi->ReturnType; index_stack[sp-1]=psi->u.ReturnIndex; if(psi->ReturnType==DEF_STRUCT){ //構造体が戻ったときはヒープ領域にインスタンスが格納されている //※後にfreeする必要あり bUseHeap[sp-1]=1; } else bUseHeap[sp-1]=0; return 1; } void CallCastOperatorProc(int &CalcType,LONG_PTR &lpCalcIndex,BOOL bCalcUseHeap,int ToType,LONG_PTR lpToIndex){ int type[10]; LONG_PTR index_stack[10]; BOOL array_bUseHeap[10]; int sp=2; if(bCalcUseHeap){ //未解放のインスタンスが存在する旨を示す警告 SetError(-105,NULL,cp); } //左辺 type[0]=CalcType; index_stack[0]=lpCalcIndex; array_bUseHeap[0]=0; type[1]=ToType; index_stack[1]=lpToIndex; array_bUseHeap[1]=0; TYPEINFO BaseTypeInfo={ToType,lpToIndex}; int iRet; iRet=CallOperatorProc(CALC_AS,&BaseTypeInfo,type,index_stack,array_bUseHeap,sp); if(iRet==1){ //成功したとき CalcType=type[0]; lpCalcIndex=index_stack[0]; return; } else if(iRet==-1){ //エラーが発行されたとき return; } //エラーを発行 SetError(-1,"キャスト演算子がオーバーロードされていません。",cp); } void CallIndexerGetterProc(CClass *pobj_Class,char *ObjectName,char *Parameter,TYPEINFO &RetTypeInfo){ std::vector subs; pobj_Class->EnumMethod( CALC_ARRAY_GET, subs ); if( subs.size() == 0 ){ return; } Opcode_CallProc(Parameter,subs[0],0,ObjectName,DEF_OBJECT); RetTypeInfo.type = subs[0]->ReturnType; RetTypeInfo.u.lpIndex = subs[0]->u.ReturnIndex; }