#include "../BasicCompiler_Common/common.h" #include "opcode.h" int ParamImpl::NewTempParameters( const string &procName, const Parameters ¶ms, int SecondParmNum ){ if( SecondParmNum == -1 ) SecondParmNum = (int)params.size(); /////////////////////////////////////////////////////// // 一時オブジェクトをあらかじめスタックに積んでおく /////////////////////////////////////////////////////// int stackItemNum = 0; useTempObject = false; BOOL bEllipse; if(params.size()){ if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1; else bEllipse=0; } else bEllipse=0; for(int i2=ParmsNum-1;i2>=0;i2--){ useTempParameters[i2] = false; if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0; if(i2==0){ if( params[i2]->GetVarName() == "_System_LocalThis" ){ //オブジェクトメンバの第一パラメータのThisポインタ continue; } } if( i2==0||i2==1 ){ if( params[i2]->GetVarName() == procName ){ //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト continue; } } Type dummyType; BOOL bByVal; if(bEllipse){ NumOpe_GetType( Parms[i2], Type(), dummyType ); bByVal=1; } else{ dummyType = *params[i2]; bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE; } if( !bByVal ){ //ポインタ参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ //ポインタ指定 continue; } if( !GetVarType( Parms[i2], Type(), FALSE ) ){ //変数ではないとき int reg = REG_RAX; Type calcType; NumOpe( ®, Parms[i2], dummyType, calcType ); if( !calcType.IsStruct() ){ //一時参照を作成 pobj_sf->push( reg ); pobj_sf->mov_sp( reg ); stackItemNum++; } //スタックフレームへコピー StackOffsetOfTempObject[i2] = pobj_sf->push(reg); stackItemNum++; bool result = CheckDifferentType( dummyType, calcType, procName.c_str(), i2); if( result ){ useTempParameters[i2] = true; useTempObject = true; types[i2] = calcType; } } } } return stackItemNum * PTR_SIZE; } void ParamImpl::DeleteTempParameters(){ /////////////////////////////////////////////////////// // 一時オブジェクトを破棄 /////////////////////////////////////////////////////// if( !useTempObject ) return; for(int i2=ParmsNum-1;i2>=0;i2--){ if( useTempParameters[i2] ){ if( types[i2].IsStruct() ){ // 構造体の一時メモリ //メモリを解放する pobj_sf->pop( REG_RCX ); //call free extern UserProc *pSub_free; op_call(pSub_free); } else{ pobj_sf->pop(); pobj_sf->pop(); } } } } void ParamImpl::SetStructParameter( int reg, const Type &baseType, const char *expression ){ ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// int object_size = baseType.GetClass().GetSize(); //mov rcx,object_size op_mov_RV(sizeof(_int64),REG_RCX,object_size); //call calloc extern UserProc *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); Type calcType; BOOL bUseHeap; int temp_reg=REG_RAX; NumOpe( &temp_reg, expression, baseType, calcType, &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( baseType, calcType, &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 ParamImpl::SetParameter( const string &procName, const Parameters ¶ms, int SecondParmNum ){ if( SecondParmNum == -1 ) SecondParmNum = (int)params.size(); /////////////////////////////////////////////////////////// // パラメータをレジスタ及びスタックフレームにセット /////////////////////////////////////////////////////////// int i2,i3; BOOL bEllipse; if( params.size() ){ if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1; else bEllipse=0; } else bEllipse=0; BOOL bHas_System_LocalThis=0; if(ParmsNum>=1){ if( params[0]->GetVarName() == "_System_LocalThis" ){ bHas_System_LocalThis=1; } } //戻り値用の変数名を取得 const char *lpszVarNameToReturn = (procName[0]==1&&procName[1]==ESC_OPERATOR)?"_System_ReturnValue":procName.c_str(); //パラメータをレジスタとスタックに格納 int ParmSize=0; int reg,temp_reg; RELATIVE_VAR RelativeVar; for(i2=ParmsNum-1;i2>=0;i2--){ if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0; if(i2==0){ if( params[i2]->GetVarName() == "_System_LocalThis" ){ //オブジェクトメンバの第一パラメータのThisポインタ continue; } } if(i2==0||i2==1){ if( params[i2]->GetVarName() == lpszVarNameToReturn ){ //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト continue; } } Type dummyType; BOOL bByVal; if(bEllipse){ NumOpe_GetType( Parms[i2], Type(), dummyType ); bByVal=1; } else{ dummyType = *params[i2]; bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE; } int xmm_temp_sw=0; if(dummyType.IsReal()&&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パラメータ",procName,i2+1); SetError(19,temp2,cp); continue; } if( dummyType.IsStruct() ){ SetStructParameter( reg, dummyType, Parms[i2] ); goto next; } temp_reg=reg; extern LONG_PTR ProcPtr_BaseIndex; LONG_PTR back_ProcPtr_BaseIndex = ProcPtr_BaseIndex; if( dummyType.IsProcPtr() ){ ProcPtr_BaseIndex = dummyType.GetIndex(); } else{ ProcPtr_BaseIndex=-1; } BOOL bCalcUseHeap; Type calcType; if( !NumOpe( &temp_reg, Parms[i2], dummyType, calcType, &bCalcUseHeap ) ){ break; } ProcPtr_BaseIndex=back_ProcPtr_BaseIndex; if( calcType.IsObject() ){ if( !dummyType.IsObject() || dummyType.IsObject() && !dummyType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){ //キャスト演算子のオーバーロードに対応する CallCastOperatorProc( reg, calcType, bCalcUseHeap,dummyType ); } } if(bEllipse){ if( calcType.IsReal() ){ //整数レジスタへコピー //※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( calcType.IsWhole() ){ //整数型の場合は、64ビットへ拡張する ExtendTypeTo64( calcType.GetBasicType(), temp_reg ); } } else{ //型チェック // TODO: _System_ReturnValueが考慮されていない? if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( dummyType, calcType, procName.c_str(), i3); if( dummyType.IsDouble() ){ //Double型へ変換 ChangeTypeToXmm_Double(calcType.GetBasicType(),reg,temp_reg); } else if( dummyType.IsSingle() ){ //Single型へ変換 ChangeTypeToXmm_Single(calcType.GetBasicType(),reg,temp_reg); } else if( dummyType.IsWhole() ){ //実数型 → 整数型 ChangeTypeToWhole(calcType.GetBasicType(),dummyType.GetBasicType(),reg,temp_reg); } } } else{ //ポインタ参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ //ポインタ指定 temp_reg=reg; Type calcType; if( !NumOpe(&temp_reg, Parms[i2]+2, dummyType, calcType) ){ break; } dummyType.PtrLevelUp(); //型チェック if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( dummyType, calcType, procName.c_str(), i3); if( calcType.IsReal() ){ //実数型 → 整数型 ChangeTypeToWhole( calcType.GetBasicType(), DEF_QWORD,reg,temp_reg); } } else{ if( useTempParameters[i2] ){ //一時オブジェクトをコピー //mov reg, qword ptr[rsp+offset] pobj_sf->ref_offset_data( reg, StackOffsetOfTempObject[i2] ); } else{ //変数のアドレスを取得 Type varType; if(GetVarOffset( false, false, Parms[i2], &RelativeVar, varType)){ if( !dummyType.IsAny() ){ //型チェックを行う if( dummyType.GetBasicType() == varType.GetBasicType() ){ if( dummyType.IsObject() ){ if( !dummyType.GetClass().IsEqualsOrSubClass( &varType.GetClass() ) ){ SetError(11,Parms[i2],cp); } } else if( dummyType.IsStruct() ){ if( !dummyType.GetClass().IsEquals( &varType.GetClass() ) ){ SetError(11,Parms[i2],cp); } } } else if( (varType.GetBasicType()&FLAG_PTR) &&((varType.GetBasicType()^FLAG_PTR)==dummyType.GetBasicType())){ //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき } else{ SetError(11,Parms[i2],cp); } } //変数アドレスをレジスタにセット SetVarPtrToReg(reg,&RelativeVar); } } } } 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((int)params.size()*sizeof(_int64)+ sizeof(_int64)/*ret用*/ ); } void ParamImpl::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); } } }