#include "stdafx.h" #include #include "../BasicCompiler_Common/common.h" #include "opcode.h" int ParamImpl::NewTempParameters( const std::string &procName, const Parameters ¶ms, int SecondParmNum ){ if( SecondParmNum == -1 ) SecondParmNum = (int)params.size(); /////////////////////////////////////////////////////// // 一時オブジェクトをあらかじめスタックに積んでおく /////////////////////////////////////////////////////// useTempObject = false; //一時参照の数 nCountOfTempObjects = 0; 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 ) ){ //変数ではないとき Type calcType; bool isNeedHeapFreeStructure; NumOpe( Parms[i2], dummyType, calcType, &isNeedHeapFreeStructure ); //↑ここでスタックに積む nCountOfTempObjects++; if( !calcType.IsStruct() ){ //一時参照を作成 //push esp compiler.codeGenerator.op_push( REG_ESP ); nCountOfTempObjects++; } bool result = CheckDifferentType( dummyType, calcType, procName.c_str(), i2); if( result ) { useTempParameters[i2] = true; isNeedFreeStructures[i2] = isNeedHeapFreeStructure; useTempObject = true; types[i2] = calcType; } } } } return nCountOfTempObjects * PTR_SIZE; } void ParamImpl::DeleteTempParameters(){ /////////////////////////////////////////////////////// // 一時オブジェクトを破棄 /////////////////////////////////////////////////////// if( !useTempObject ) return; for(int i2=ParmsNum-1;i2>=0;i2--){ if( useTempParameters[i2] ){ if( types[i2].IsStruct() ) { // 構造体の一時メモリ if( isNeedFreeStructures[i2] ) { //メモリを解放する //call free extern const UserProc *pSub_free; compiler.codeGenerator.op_call(pSub_free); } else { //pop ... 参照を消す compiler.codeGenerator.op_add_esp( PTR_SIZE ); } } else { if( types[i2].Is64() ) { //pop ... 参照を消す //pop ... 上位32ビット //pop ... 下位32ビット compiler.codeGenerator.op_add_esp( PTR_SIZE * 3 ); } else { //pop ... 参照を消す //pop ... 値を消す compiler.codeGenerator.op_add_esp( PTR_SIZE * 2 ); } } } } } void ParamImpl::SetStructParameter( const Type &baseType, const char *expression ){ int object_size = baseType.GetClass().GetSize(); //push object_size compiler.codeGenerator.op_push_V(object_size); //call calloc extern const UserProc *pSub_calloc; compiler.codeGenerator.op_call(pSub_calloc); //push eax(ここでプッシュされた値が実際にパラメータとして引き渡される) compiler.codeGenerator.op_push(REG_EAX); //push eax compiler.codeGenerator.op_push(REG_EAX); Type calcType; bool isNeedHeapFreeStructure; NumOpe( expression, baseType, calcType, &isNeedHeapFreeStructure ); // ※スタックにある二つのデータ(コピー先、コピー元)の値を必要とする SetStructVariable( baseType, calcType, isNeedHeapFreeStructure ); } int ParamImpl::SetParameter( const std::string &procName, const Parameters ¶ms, int SecondParmNum, const UserProc *pUserProc ){ 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; RELATIVE_VAR RelativeVar; int nCountOfNowTempObjects = 0; 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; // 型パラメータを解決 ResolveFormalGenericTypeParameter( dummyType, leftType, pUserProc ); } if(bByVal==1){ //値参照 /* if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ char temp2[255]; sprintf(temp2,"%s関数の第%dパラメータ",procName.c_str(),i2+1); compiler.errorMessenger.Output(19,temp2,cp); continue; } */ if( dummyType.IsStruct() ){ SetStructParameter( dummyType, Parms[i2] ); goto next; } Type calcType; bool isNeedHeapFreeStructure; if( !NumOpe( Parms[i2], dummyType, calcType, &isNeedHeapFreeStructure ) ) { break; } if( calcType.IsObject() ) { if( !dummyType.IsObject() || dummyType.IsObject() && !dummyType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ) { //キャスト演算子のオーバーロードに対応する CallCastOperatorProc( calcType, isNeedHeapFreeStructure,dummyType ); } } if(!bEllipse){ //型チェック // TODO: _System_ReturnValueが考慮されていない? if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( dummyType, calcType, procName.c_str(), i3); } if( dummyType.IsDouble() ){ ChangeTypeToDouble( calcType.GetBasicType() ); ParmSize+=sizeof(long)*2; } else if( dummyType.IsSingle() ){ ChangeTypeToSingle( calcType.GetBasicType() ); ParmSize+=sizeof(long); } else if( dummyType.Is64() ){ ChangeTypeToInt64( calcType.GetBasicType() ); ParmSize+=sizeof(long)*2; } else if( dummyType.IsLong() || dummyType.IsDWord() || dummyType.IsPointer() || dummyType.IsObject() || dummyType.IsStruct() ){ ChangeTypeToLong( calcType.GetBasicType() ); ParmSize+=sizeof(long); } else if( dummyType.IsInteger() || dummyType.IsWord() ){ ChangeTypeToInteger( calcType.GetBasicType() ); ParmSize+=sizeof(long); } else if( dummyType.IsSByte() || dummyType.IsByte() || dummyType.IsBoolean() ){ ChangeTypeToByte( calcType.GetBasicType() ); ParmSize+=sizeof(long); } else{ compiler.errorMessenger.Output(300,NULL,cp); } } else{ //ポインタ参照 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){ //ポインタ指定 Type calcType; if( !NumOpe( Parms[i2]+2, dummyType, calcType) ){ break; } ChangeTypeToLong( calcType.GetBasicType() ); dummyType.PtrLevelUp(); //型チェック if(bHas_System_LocalThis) i3=i2-1; else i3=i2; CheckDifferentType( dummyType, calcType, procName.c_str(), i3); } else{ if( useTempParameters[i2] ){ //一時オブジェクトをコピー if( !types[i2].IsStruct() ){ // 一時参照のための領域を考慮する nCountOfNowTempObjects++; } nCountOfNowTempObjects++; //mov eax, dword ptr[esp+offset] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_ESP, ( ( ParmsNum - i2 - 1 ) + ( nCountOfTempObjects - nCountOfNowTempObjects ) ) * PTR_SIZE, MOD_BASE_DISP32 ); //push eax compiler.codeGenerator.op_push(REG_EAX); } 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() ) ){ compiler.errorMessenger.Output(11,Parms[i2],cp); } } else if( dummyType.IsStruct() ){ if( !dummyType.GetClass().IsEquals( &varType.GetClass() ) ){ compiler.errorMessenger.Output(11,Parms[i2],cp); } } } else if( (varType.GetBasicType()&FLAG_PTR) &&((varType.GetBasicType()^FLAG_PTR)==dummyType.GetBasicType())){ //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき } else{ compiler.errorMessenger.Output(11,Parms[i2],cp); } } //変数アドレスをレジスタにセット SetVarPtrToEax(&RelativeVar); //push eax compiler.codeGenerator.op_push(REG_EAX); } } } ParmSize+=PTR_SIZE; } next:; } return ParmSize; }