#include "../BasicCompiler_Common/common.h" #include "Opcode.h" void FreeTempObject(int reg,CClass *pobj_c){ if(!IsSafeReg(reg)) SetError(300,NULL,cp); //////////////////////////////////////////////// // 演算過程で利用した一時オブジェクトを破棄 // Thisポインタをr14レジスタを介して渡す //////////////////////////////////////////////// if(pobj_c->DestructorMemberSubIndex!=-1){ //mov rcx,reg op_mov_RR(REG_RCX,reg); //call DestructorProcAddr op_call(pobj_c->ppobj_Method[pobj_c->DestructorMemberSubIndex]->psi); } //mov rcx,reg op_mov_RR(REG_RCX,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]; SUBINFO **ppsi; int num; ppsi=pobj_c->GetOperatorSubInfo(idCalc,num); if(num==0){ HeapDefaultFree(ppsi); return 0; } //項の数 BOOL bTwoTerm=1; if(idCalc==CALC_AS) bTwoTerm=0; int i; BOOL bReturnTypeIsObject=1; TYPEINFO ReturnType={DEF_OBJECT,ppsi[0]->u.ReturnIndex}; for(i=0;iReturnType!=DEF_OBJECT) bReturnTypeIsObject=0; } if(bReturnTypeIsObject==0){ if(pBaseTypeInfo){ if(pBaseTypeInfo->type==DEF_OBJECT){ bReturnTypeIsObject=1; ReturnType.u.lpIndex=pBaseTypeInfo->u.lpIndex; } } } ///////////////////////////////////////////// // オーバーロード解決用のパラメータを設定 ///////////////////////////////////////////// PARAMETER_INFO *ppi; int iParmNum=0; //_System_LocalThis ppi=(PARAMETER_INFO *)HeapAlloc(hHeap,0,sizeof(PARAMETER_INFO)*3); ppi[iParmNum].bArray=0; ppi[iParmNum].bByVal=0; ppi[iParmNum].name=0; ppi[iParmNum].type=DEF_PTR_VOID; ppi[iParmNum].u.index=-1; ppi[iParmNum].SubScripts[0]=-1; iParmNum++; 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,ppsi,num,ppi,iParmNum,pBaseTypeInfo); HeapDefaultFree(ppsi); 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; if(type[sp-1]==DEF_OBJECT) right_side_size=PTR_SIZE; else right_side_size=GetTypeSize(type[sp-1],index_stack[sp-1]); if(bTwoTerm){ if(psi->pParmInfo[1].type==DEF_OBJECT&&psi->pParmInfo[1].bByVal){ //一時オブジェクトはメソッド内で破棄される bUseHeap[sp-1]=0; } } if(psi->ReturnType==DEF_OBJECT){ ////////////////////////////////////////////////////// // 戻り値にオブジェクト インスタンスを持つ場合 // ※ByRef _System_ReturnObject パラメータ用領域を取得 ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// int object_size; object_size=GetSizeOfClass(psi->u.Return_pobj_c); //mov rcx,object_size op_mov_RV(sizeof(_int64),REG_RCX,object_size); //call calloc extern SUBINFO *pSub_calloc; op_call(pSub_calloc); //mov r13,rax op_mov_RR(REG_R13,REG_RAX); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// } int reg1,reg2; if(bTwoTerm){ //右の項(実数の場合が未完成) SetOneTermToReg_Whole64Calc(type[sp-1],®2); pobj_reg->UnlockReg(); } //左の項 SetOneTermToReg_Whole64Calc(DEF_INT64,®1); pobj_reg->UnlockReg(); //ヒープ解放用に退避 if(bUseHeap[sp-1]){ //mov qword ptr[rsp+offset],reg2 ※スタックフレームを利用 pobj_sf->push(reg2); } if(bUseHeap[sp-2]){ //mov qword ptr[rsp+offset],reg1 ※スタックフレームを利用 pobj_sf->push(reg1); } ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// if(reg1==REG_RDX||reg1==REG_R8){ //mov r14,reg1 op_mov_RR(REG_R14,reg1); reg1=REG_R14; } if(bTwoTerm){ if(psi->ReturnType==DEF_OBJECT){ //mov r8,reg2 op_mov_RR(REG_R8,reg2); } else{ //mov rdx,reg2 op_mov_RR(REG_RDX,reg2); } } if(psi->ReturnType==DEF_OBJECT){ //mov rdx,r13 op_mov_RR(REG_RDX,REG_R13); } //mov rcx,reg1 op_mov_RR(REG_RCX,reg1); //call operator_proc op_call(psi); if(psi->ReturnType!=-1){ //戻り値を一時的に退避 //mov r13,rax op_mov_RR(REG_R13,REG_RAX); } ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// if(bUseHeap[sp-2]||bUseHeap[sp-1]){ ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// if(bUseHeap[sp-2]){ //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R14); FreeTempObject(REG_R14,(CClass *)index_stack[sp-2]); } if(bUseHeap[sp-1]){ //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R14); FreeTempObject(REG_R14,(CClass *)index_stack[sp-1]); } ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// } if(psi->ReturnType!=-1){ //戻り値をreg1にセット reg1=pobj_reg->LockReg(); //mov reg1,r13 op_mov_RR(reg1,REG_R13); } sp--; type[sp-1]=psi->ReturnType; index_stack[sp-1]=psi->u.ReturnIndex; if(psi->ReturnType==DEF_OBJECT){ //Object型が戻ったときはヒープ領域にインスタンスが格納されている //※後にfreeする必要あり bUseHeap[sp-1]=1; } else bUseHeap[sp-1]=0; return 1; } void CallCastOperatorProc(int reg,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; int iRet; ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// //regを第一項目としてロック pobj_reg=new CRegister(reg); pobj_reg->LockReg(); if(bCalcUseHeap){ /* //未解放のインスタンスが存在する場合 //※専用のローカル変数を用意し、メモリリークを回避 char temporary[VN_SIZE],temp2[VN_SIZE]; //////////////////////////////// // 一時オブジェクト変数を用意 //////////////////////////////// char szTempVarName[255]; GetTypeName(CalcType,lpCalcIndex,temp2); sprintf(szTempVarName,"_System_strDummy%d",obp); wsprintf(temporary,"%s%c%c%s",szTempVarName,1,ESC_AS,temp2); InsertDimStatement_ToProcHead(temporary); RELATIVE_VAR VarRelativeVar; int VarType; LONG_PTR lpVarIndex; if(!GetVarOffsetReadOnly( szTempVarName, &VarType, &VarRelativeVar, &lpVarIndex)) return; CClass *pobj_c; pobj_c=(CClass *)lpCalcIndex; if(pobj_c->DestructorMemberSubIndex!=-1){ ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// //ループの場合、古い一時オブジェクトのデストラクタを呼ぶ //rcxに変数アドレスをコピー SetVarPtrToReg(REG_RCX,&VarRelativeVar); //call destructor OpBuffer[obp++]=(char)0xE8; pobj_SubAddrSchedule->add(pobj_c->ppobj_Method[pobj_c->DestructorMemberSubIndex]->psi,1); obp+=sizeof(long); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// } //mov r15,reg op_mov_RR(REG_R15,reg); int object_size; object_size=GetSizeOfClass((CClass *)lpVarIndex); //mov rcx,object_size op_mov_RV(sizeof(_int64),REG_RCX,object_size); //rdiに変数アドレスをコピー SetVarPtrToReg(REG_RDI,&VarRelativeVar); //mov rsi,reg op_mov_RR(REG_RSI,reg); //mov r14,rdi op_mov_RR(REG_R14,REG_RDI); pobj_BlockReg->lock(REG_R14); //rep movs byte ptr[rdi],byte ptr[rsi] op_rep_movs(sizeof(BYTE)); ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// //mov rcx,r15 op_mov_RR(REG_RCX,REG_R15); //call free extern SUBINFO *pSub_free; OpBuffer[obp++]=(char)0xE8; pobj_SubAddrSchedule->add(pSub_free,1); obp+=sizeof(long); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// //mov reg,r14 op_mov_RR(reg,REG_R14); pobj_BlockReg->unlock(REG_R14); */ //未解放のインスタンスが存在する旨を示す警告 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}; iRet=CallOperatorProc(CALC_AS,&BaseTypeInfo,type,index_stack,array_bUseHeap,sp); pobj_reg->UnlockReg(); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// if(iRet==1){ //成功したとき CalcType=type[0]; lpCalcIndex=index_stack[0]; return; } else if(iRet==-1){ //エラーが発行されたとき return; } //エラーを発行 SetError(-1,"キャスト演算子がオーバーロードされていません。",cp); } void CallArrayOperatorProc(int reg,CClass *pobj_Class,char *ObjectName,char *Parameter,TYPEINFO &RetTypeInfo){ SUBINFO **ppsi; int num; ppsi=pobj_Class->GetOperatorSubInfo(CALC_ARRAY_GET,num); if(num==0){ HeapDefaultFree(ppsi); return; } ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// RetTypeInfo.type=Opcode_CallProc(Parameter,ppsi[0],&RetTypeInfo.u.lpIndex,0,ObjectName,DEF_OBJECT); //mov reg,rax op_mov_RR(reg,REG_RAX); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// HeapDefaultFree(ppsi); }