#include "../BasicCompiler_Common/common.h" #include "opcode.h" int CParameter::NewTempParameters( const char *FuncName,PARAMETER_INFO *ppi,int pi_num,int SecondParmNum ){ /////////////////////////////////////////////////////// // 一時オブジェクトをあらかじめスタックに積んでおく /////////////////////////////////////////////////////// int stackItemNum = 0; useTempObject = false; BOOL bEllipse; if(pi_num){ if(ppi[pi_num-1].type==DEF_ELLIPSE) bEllipse=1; else bEllipse=0; } else bEllipse=0; for(int i2=ParmsNum-1;i2>=0;i2--){ useTempParameters[i2] = false; if(bEllipse&&i2<=pi_num-2) bEllipse=0; if(i2==0&&ppi[i2].name){ if(lstrcmp(ppi[i2].name,"_System_LocalThis")==0){ //オブジェクトメンバの第一パラメータのThisポインタ continue; } } if((i2==0||i2==1)&&ppi[i2].name){ if(lstrcmp(ppi[i2].name,FuncName)==0){ //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト continue; } } TYPEINFO DummyTypeInfo; BOOL bByVal; if(bEllipse){ DummyTypeInfo.type=NumOpe_GetType(Parms[i2],NULL,&DummyTypeInfo.u.lpIndex); bByVal=1; } else{ DummyTypeInfo.type=ppi[i2].type; DummyTypeInfo.u.lpIndex=ppi[i2].u.index; bByVal=ppi[i2].bByVal; } if( !bByVal ){ //ポインタ参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ //ポインタ指定 continue; } LONG_PTR lpVarIndex; if( GetVarType( Parms[i2], &lpVarIndex, FALSE ) == -1 ){ //変数ではないとき int reg = REG_RAX; int type = NumOpe( ®, Parms[i2], DummyTypeInfo.type, DummyTypeInfo.u.lpIndex, &lpVarIndex ); if( type == DEF_OBJECT ){ //一時参照を作成 pobj_sf->push( reg ); pobj_sf->mov_sp( reg ); stackItemNum++; } //スタックフレームへコピー StackOffsetOfTempObject[i2] = pobj_sf->push(reg); stackItemNum++; bool result = CheckDifferentType( DummyTypeInfo.type, DummyTypeInfo.u.lpIndex, type, lpVarIndex, FuncName, i2); if( result ){ useTempParameters[i2] = true; useTempObject = true; types[i2].type = type; types[i2].u.lpIndex = lpVarIndex; } } } } return stackItemNum * PTR_SIZE; } void CParameter::DeleteTempParameters(){ /////////////////////////////////////////////////////// // 一時オブジェクトを破棄 /////////////////////////////////////////////////////// if( !useTempObject ) return; for(int i2=ParmsNum-1;i2>=0;i2--){ if( useTempParameters[i2] ){ if( types[i2].type == DEF_STRUCT ){ // 構造体の一時メモリ //メモリを解放する pobj_sf->pop( REG_RCX ); //call free extern SUBINFO *pSub_free; op_call(pSub_free); } else if( types[i2].type == DEF_OBJECT ){ pobj_sf->pop(); pobj_sf->pop(); } else{ SetError(300,NULL,cp); } } } } void CParameter::SetStructParameter(int reg,CClass *pobj_Class,LPSTR Parameter){ ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// int object_size = pobj_Class->GetSize(); //mov rcx,object_size op_mov_RV(sizeof(_int64),REG_RCX,object_size); //call calloc extern SUBINFO *pSub_calloc; op_call(pSub_calloc); //mov r11,rax op_mov_RR(REG_R11,REG_RAX); //mov qword ptr[rsp+offset],r11 ※スタックフレームを利用 pobj_sf->push(REG_R11); TYPEINFO BaseType={DEF_STRUCT,(LONG_PTR)pobj_Class}; TYPEINFO CalcType; CalcType.type=NumOpe_GetType(Parameter,&BaseType,&CalcType.u.lpIndex); /* TODO: 消す if( pobj_Class->GetCopyConstructorMethod() && CalcType.type==DEF_OBJECT&&CalcType.u.pobj_Class==pobj_Class){ //////////////////////////////////// // コピーコンストラクタを呼び出す //////////////////////////////////// BOOL bUseHeap; int temp_reg=REG_RDX; CalcType.type=NumOpe(&temp_reg,Parameter,DEF_OBJECT,(LONG_PTR)pobj_Class,&CalcType.u.lpIndex,&bUseHeap); if(bUseHeap){ //mov r14,rdx op_mov_RR(REG_R14,REG_RDX); } //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->ref(REG_R11); //mov rcx,this op_mov_RR(REG_RCX,REG_R11); //call constructor op_call(pobj_Class->GetCopyConstructorMethod()->psi); if(bUseHeap){ FreeTempObject(REG_R14,pobj_Class); } } else{ if( pobj_Class->GetConstructorMethod() ){ //////////////////////////////// // コンストラクタを呼び出す //////////////////////////////// //mov rcx,this op_mov_RR(REG_RCX,REG_R11); //call constructor op_call(pobj_Class->GetConstructorMethod()->psi); } */ BOOL bUseHeap; int temp_reg=REG_RAX; CalcType.type=NumOpe(&temp_reg,Parameter,DEF_STRUCT,(LONG_PTR)pobj_Class,&CalcType.u.lpIndex,&bUseHeap); //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->ref(REG_R11); RELATIVE_VAR RelativeVar; RelativeVar.bOffsetOffset=0; RelativeVar.offset=0; RelativeVar.dwKind=VAR_DIRECTMEM; SetStructVariableFromRax((LONG_PTR)pobj_Class,CalcType.type,CalcType.u.lpIndex,&RelativeVar,bUseHeap); //} //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R11); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// //mov reg,r11 op_mov_RR(reg,REG_R11); } void CParameter::SetParameter(const char *FuncName,PARAMETER_INFO *ppi,int pi_num,int SecondParmNum){ /////////////////////////////////////////////////////////// // パラメータをレジスタ及びスタックフレームにセット /////////////////////////////////////////////////////////// int i2,i3; BOOL bEllipse; if(pi_num){ if(ppi[pi_num-1].type==DEF_ELLIPSE) bEllipse=1; else bEllipse=0; } else bEllipse=0; BOOL bHas_System_LocalThis=0; if(ParmsNum>=1){ if(lstrcmp(ppi[0].name,"_System_LocalThis")==0) bHas_System_LocalThis=1; } //戻り値用の変数名を取得 const char *lpszVarNameToReturn = (FuncName[0]==1&&FuncName[1]==ESC_OPERATOR)?"_System_ReturnValue":FuncName; //パラメータをレジスタとスタックに格納 int CalcType; LONG_PTR lpCalcIndex; BOOL bCalcUseHeap; int ParmSize=0; int reg,temp_reg; RELATIVE_VAR RelativeVar; for(i2=ParmsNum-1;i2>=0;i2--){ if(bEllipse&&i2<=pi_num-2) bEllipse=0; if(i2==0&&ppi[i2].name){ if(lstrcmp(ppi[i2].name,"_System_LocalThis")==0){ //オブジェクトメンバの第一パラメータのThisポインタ continue; } } if((i2==0||i2==1)&&ppi[i2].name){ if(lstrcmp(ppi[i2].name,lpszVarNameToReturn)==0){ //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト continue; } } TYPEINFO DummyTypeInfo; BOOL bByVal; if(bEllipse){ DummyTypeInfo.type=NumOpe_GetType(Parms[i2],NULL,&DummyTypeInfo.u.lpIndex); bByVal=1; } else{ DummyTypeInfo.type=ppi[i2].type; DummyTypeInfo.u.lpIndex=ppi[i2].u.index; bByVal=ppi[i2].bByVal; } int xmm_temp_sw=0; if(IsRealNumberType(DummyTypeInfo.type)&&bByVal){ //実数型 if(i2==0) reg=REG_XMM0; else if(i2==1) reg=REG_XMM1; else if(i2==2) reg=REG_XMM2; else if(i2==3) reg=REG_XMM3; else{ reg=REG_XMM0; xmm_temp_sw=1; } } else{ //整数型 if(i2==0) reg=REG_RCX; else if(i2==1) reg=REG_RDX; else if(i2==2) reg=REG_R8; else if(i2==3) reg=REG_R9; else reg=REG_RAX; } if(bByVal==1){ //値参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ char temp2[255]; sprintf(temp2,"%s関数の第%dパラメータ",FuncName,i2+1); SetError(19,temp2,cp); continue; } if(DummyTypeInfo.type==DEF_STRUCT){ SetStructParameter(reg,DummyTypeInfo.u.pobj_Class,Parms[i2]); goto next; } temp_reg=reg; extern LONG_PTR ProcPtr_BaseIndex; LONG_PTR back_ProcPtr_BaseIndex; back_ProcPtr_BaseIndex=ProcPtr_BaseIndex; if(DummyTypeInfo.type==DEF_PTR_PROC) ProcPtr_BaseIndex=DummyTypeInfo.u.lpIndex; else ProcPtr_BaseIndex=-1; CalcType=NumOpe(&temp_reg,Parms[i2],DummyTypeInfo.type,DummyTypeInfo.u.lpIndex,&lpCalcIndex,&bCalcUseHeap); ProcPtr_BaseIndex=back_ProcPtr_BaseIndex; if(CalcType==-1) break; if(CalcType==DEF_OBJECT){ if( DummyTypeInfo.type != DEF_OBJECT || DummyTypeInfo.type == DEF_OBJECT && !DummyTypeInfo.u.pobj_Class->IsEqualsOrSubClass( (CClass *)lpCalcIndex ) ){ //キャスト演算子のオーバーロードに対応する CallCastOperatorProc(reg,CalcType,lpCalcIndex,bCalcUseHeap,DummyTypeInfo.type,DummyTypeInfo.u.lpIndex); } } if(bEllipse){ if(IsRealNumberType(CalcType)){ //整数レジスタへコピー //※cdeclの拡張パラメータは実数の場合も汎用レジスタで引渡し if(0<=i2&&i2<=3){ if(i2==0) reg=REG_RCX; else if(i2==1) reg=REG_RDX; else if(i2==2) reg=REG_R8; else if(i2==3) reg=REG_R9; //movd reg,temp_reg op_movd_RX(reg,temp_reg); } } else if(IsWholeNumberType(CalcType)){ //整数型の場合は、64ビットへ拡張する ExtendTypeTo64(CalcType,temp_reg); } } else{ //型チェック // TODO: _System_ReturnValueが考慮されていない? if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( DummyTypeInfo.type, DummyTypeInfo.u.lpIndex, CalcType, lpCalcIndex, FuncName, i3); if(DummyTypeInfo.type==DEF_DOUBLE){ //Double型へ変換 ChangeTypeToXmm_Double(CalcType,reg,temp_reg); } else if(DummyTypeInfo.type==DEF_SINGLE){ //Single型へ変換 ChangeTypeToXmm_Single(CalcType,reg,temp_reg); } else if(IsWholeNumberType(DummyTypeInfo.type)){ //実数型 → 整数型 ChangeTypeToWhole(CalcType,DummyTypeInfo.type,reg,temp_reg); } } } else{ //ポインタ参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ //ポインタ指定 temp_reg=reg; CalcType=NumOpe(&temp_reg,Parms[i2]+2,0,0,&lpCalcIndex); if(CalcType==-1) break; int ptr_type; ptr_type=GetPtrType(DummyTypeInfo.type,DummyTypeInfo.u.lpIndex); //型チェック if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( ptr_type, DummyTypeInfo.u.lpIndex, CalcType, lpCalcIndex, FuncName, i3); if(IsRealNumberType(CalcType)){ //実数型 → 整数型 ChangeTypeToWhole(CalcType,DEF_QWORD,reg,temp_reg); } } else{ //変数のアドレスを取得 int VarType; LONG_PTR lpVarIndex; if(GetVarOffset( false, false, Parms[i2], &VarType, &RelativeVar, &lpVarIndex)){ if(DummyTypeInfo.type!=DEF_ANY){ //型チェックを行う if(DummyTypeInfo.type==VarType){ if(DummyTypeInfo.type==DEF_OBJECT){ if( !DummyTypeInfo.u.pobj_Class->IsEqualsOrSubClass( (CClass *)lpVarIndex ) ){ SetError(11,Parms[i2],cp); } } else if(DummyTypeInfo.type==DEF_STRUCT){ if( !DummyTypeInfo.u.pobj_Class->IsEquals( (CClass *)lpVarIndex ) ){ SetError(11,Parms[i2],cp); } } } else if((VarType&FLAG_PTR)&&((VarType^FLAG_PTR)==DummyTypeInfo.type)){ //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき } else{ SetError(11,Parms[i2],cp); } } //変数アドレスをレジスタにセット SetVarPtrToReg(reg,&RelativeVar); } else{ //一時オブジェクトをコピー //mov reg, qword ptr[rsp+offset] pobj_sf->ref_offset_data( reg, StackOffsetOfTempObject[i2] ); //VarType = NumOpe( ®, Parms[i2], DummyTypeInfo.type, DummyTypeInfo.u.lpIndex, &lpVarIndex ); } } } next: if(reg==REG_RAX){ //スタックフレームへコピー //mov qword ptr[rsp+offset],rax op_mov_MR(sizeof(_int64),REG_RAX,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32); } else if(xmm_temp_sw){ //スタックフレームへコピー //movlpd qword ptr[rsp+offset],xmm0 op_movlpd_MR(REG_XMM0,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32); } ///////////////////// // レジスタをロック ///////////////////// if(0<=i2&&i2<=3){ // ※rcx, rdx, r8, r9の場合のみ pobj_BlockReg->lock(reg); } } //パラメータが収まるだけのスタックフレームを確保 pobj_sf->parameter_allocate(pi_num*sizeof(_int64)+ sizeof(_int64)/*ret用*/ ); } void CParameter::BackupParameter(int pi_num){ /////////////////////////////////////////////////////////// // スタックフレームに存在する既存のパラメータをバックアップ /////////////////////////////////////////////////////////// int i2; for(i2=0;i2push(REG_R14); } if(3=0;i2--){ ///////////////////// // 復元 ///////////////////// if(3pop(REG_R14); //mov qword ptr[rsp+offset],r14 op_mov_MR(sizeof(_int64),REG_R14,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32); } } }