#include "stdafx.h" #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" void FreeTempObject(int reg,const CClass *pobj_c){ if(!IsSafeReg(reg)) compiler.errorMessenger.Output(300,NULL,cp); //////////////////////////////////////////////// // 演算過程で利用した一時オブジェクトを破棄 // Thisポインタをr14レジスタを介して渡す //////////////////////////////////////////////// const CMethod *method = pobj_c->GetDestructorMethod(); if( method ){ //mov rcx,reg compiler.codeGenerator.op_mov_RR(REG_RCX,reg); //call DestructorProcAddr compiler.codeGenerator.op_call( &method->GetUserProc() ); } //mov rcx,reg compiler.codeGenerator.op_mov_RR(REG_RCX,reg); //call free extern const UserProc *pSub_free; compiler.codeGenerator.op_call(pSub_free); } int CallOperatorProc(BYTE idCalc, const Type &baseType, int *type_stack,LONG_PTR *index_stack,bool isNeedHeapFreeStructureStack[],int &sp) { Type leftType( type_stack[sp-2], index_stack[sp-2] ); Type rightType( type_stack[sp-1] & (~FLAG_CAST), index_stack[sp-1] ); //オーバーロードされたオペレータ関数を呼び出す const CClass *pobj_c = &leftType.GetClass(); std::vector subs; pobj_c->GetDynamicMethods().Enum( idCalc, subs ); if( subs.size() == 0 ){ return 0; } //項の数 BOOL bTwoTerm=1; if(idCalc==CALC_AS) bTwoTerm=0; ///////////////////////////////////////////// // オーバーロード解決用のパラメータを設定 ///////////////////////////////////////////// Parameters params; if(bTwoTerm) { params.push_back( new Parameter( "", rightType ) ); } //オーバーロードを解決 char temporary[255]; if(idCalc==CALC_EQUAL) lstrcpy(temporary,"=="); else GetCalcName(idCalc,temporary); const UserProc *pUserProc = OverloadSolution( temporary, subs, params, baseType, leftType ); if(!pUserProc){ if(bTwoTerm){ delete params[0]; } return -1; } else{ //オーバーロードされていないが、パラメータ個数が一致しないとき if(params.size()!=pUserProc->Params().size()){ if(bTwoTerm){ delete params[0]; } return -1; } } for(int i=0;i<(int)params.size();i++){ CheckDifferentType( *pUserProc->Params()[i], *params[i], NULL, i); } if(bTwoTerm){ delete params[0]; } int right_side_size = rightType.GetSize(); if(bTwoTerm){ if( pUserProc->RealParams()[1]->IsStruct() &&pUserProc->RealParams()[1]->IsRef() == false ){ //一時オブジェクトはメソッド内で破棄される isNeedHeapFreeStructureStack[sp-1] = false; } } if( pUserProc->ReturnType().IsStruct() ){ ////////////////////////////////////////////////////// // 戻り値に構造体インスタンスを持つ場合 // ※ByRef _System_ReturnValue パラメータ用領域を取得 ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// int object_size = pUserProc->ReturnType().GetClass().GetSize(); //mov rcx,object_size compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RCX,object_size); //call calloc extern const UserProc *pSub_calloc; compiler.codeGenerator.op_call(pSub_calloc); //mov r13,rax compiler.codeGenerator.op_mov_RR(REG_R13,REG_RAX); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// } int reg1,reg2; if(bTwoTerm){ //右の項(実数の場合が未完成) SetOneTermToReg_Whole64Calc(type_stack[sp-1],®2); pobj_reg->UnlockReg(); if( !pUserProc->RealParams()[1]->IsRef() == false ){ //一時参照を作成 pobj_sf->push( reg2 ); pobj_sf->mov_sp( reg2 ); } } //左の項 SetOneTermToReg_Whole64Calc(DEF_INT64,®1); pobj_reg->UnlockReg(); //ヒープ解放用に退避 if(isNeedHeapFreeStructureStack[sp-1]){ //mov qword ptr[rsp+offset],reg2 ※スタックフレームを利用 pobj_sf->push(reg2); } if(isNeedHeapFreeStructureStack[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 compiler.codeGenerator.op_mov_RR(REG_R14,reg1); reg1=REG_R14; } if(bTwoTerm){ if( pUserProc->ReturnType().IsStruct() ){ //mov r8,reg2 compiler.codeGenerator.op_mov_RR(REG_R8,reg2); } else{ //mov rdx,reg2 compiler.codeGenerator.op_mov_RR(REG_RDX,reg2); } } if( pUserProc->ReturnType().IsStruct() ){ //mov rdx,r13 compiler.codeGenerator.op_mov_RR(REG_RDX,REG_R13); } //mov rcx,reg1 compiler.codeGenerator.op_mov_RR(REG_RCX,reg1); //call operator_proc compiler.codeGenerator.op_call(pUserProc); if( !pUserProc->ReturnType().IsNull() ){ //戻り値を一時的に退避 //mov r13,rax compiler.codeGenerator.op_mov_RR(REG_R13,REG_RAX); } ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// if( isNeedHeapFreeStructureStack[sp-2] || isNeedHeapFreeStructureStack[sp-1] ) { ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// if( isNeedHeapFreeStructureStack[sp-2] ) { //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R14); FreeTempObject(REG_R14,(CClass *)index_stack[sp-2]); } if( isNeedHeapFreeStructureStack[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(bTwoTerm){ if( !pUserProc->RealParams()[1]->IsRef() == false ){ //一時参照を破棄 pobj_sf->pop(); } } if( !pUserProc->ReturnType().IsNull() ){ //戻り値をreg1にセット reg1=pobj_reg->LockReg(); //mov reg1,r13 compiler.codeGenerator.op_mov_RR(reg1,REG_R13); } sp--; type_stack[sp-1]=pUserProc->ReturnType().GetBasicType(); index_stack[sp-1]=pUserProc->ReturnType().GetIndex(); if( pUserProc->ReturnType().IsStruct() ) { //構造体が戻ったときはヒープ領域にインスタンスが格納されている //※後にfreeする必要あり isNeedHeapFreeStructureStack[sp-1] = true; } else { isNeedHeapFreeStructureStack[sp-1] = false; } return 1; } void CallCastOperatorProc(int reg,Type &calcType,BOOL bCalcUseHeap,const Type &toType){ int type_stack[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){ //未解放のインスタンスが存在する旨を示す警告 compiler.errorMessenger.Output(-105,NULL,cp); } //左辺 type_stack[0]=calcType.GetBasicType(); index_stack[0]=calcType.GetIndex(); array_bUseHeap[0]=0; type_stack[1]=toType.GetBasicType(); index_stack[1]=toType.GetIndex(); array_bUseHeap[1]=0; iRet=CallOperatorProc(CALC_AS,toType,type_stack,index_stack,array_bUseHeap,sp); pobj_reg->UnlockReg(); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// if(iRet==1){ //成功したとき calcType.SetType( type_stack[0], index_stack[0] ); return; } else if(iRet==-1){ //エラーが発行されたとき return; } //エラーを発行 compiler.errorMessenger.Output(-1,"キャスト演算子がオーバーロードされていません。",cp); } //インデクサ(getter)を呼び出す void CallIndexerGetterProc(int reg, const Type &classType, const char *ObjectName,char *Parameter,Type &resultType, DWORD dwProcFlags ){ std::vector subs; classType.GetClass().GetDynamicMethods().Enum( CALC_ARRAY_GET, subs ); if( subs.size() == 0 ){ return; } const UserProc *pUserProc = subs[0]; ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// Opcode_CallProc(Parameter,pUserProc,dwProcFlags,ObjectName); resultType = pUserProc->ReturnType(); //mov reg,rax compiler.codeGenerator.op_mov_RR(reg,REG_RAX); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// // 型パラメータを解決 ResolveFormalGenericTypeParameter( resultType, classType, pUserProc ); }