#include "../BasicCompiler_Common/common.h" #include "Opcode.h" void ChangeTypeToDouble_ToFpuReg(int OldType){ //現在のスタックの内容を実数レジスタに保存する //NumOpeの直後専用 if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] op_fld_ptr_esp(DEF_DOUBLE); //add esp,8 op_add_esp(8); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //add esp,4 op_add_esp(4); } else if(OldType==DEF_LONG){ //fild dword ptr[esp] op_fld_ptr_esp(DEF_LONG); //add esp,4 op_add_esp(4); } else if(OldType==DEF_DWORD){ //pop eax op_pop(REG_EAX); //push 0 op_push_V(0); //push eax op_push(REG_EAX); //fild qword ptr[esp] OpBuffer[obp++]=(char)0xDF; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; //add esp,8 op_add_esp(8); } } void ChangeTypeToDouble(int OldType){ //現在のスタックの内容をdouble型に変換する //NumOpeの直後専用 if(OldType==DEF_DOUBLE) return; else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 op_sub_esp(4); //fstp qword ptr[esp] OpBuffer[obp++]=(char)0xDD; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //64ビット整数型 //fild qword ptr[esp] op_fld_ptr_esp(DEF_INT64); //fstp qword ptr[esp] OpBuffer[obp++]=(char)0xDD; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else if(IsWholeNumberType(OldType)){ //その他整数型 if(IsSignedType(OldType)){ //符号あり if(OldType==DEF_INTEGER || (isUnicode&&OldType==DEF_CHAR)){ //pop eax op_pop(REG_EAX); //movsx eax,ax OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0xBF; OpBuffer[obp++]=(char)0xC0; //push eax op_push(REG_EAX); } else if(OldType==DEF_SBYTE || (isUnicode==false&&OldType==DEF_CHAR)){ //pop eax op_pop(REG_EAX); //movsx eax,al OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0xBE; OpBuffer[obp++]=(char)0xC0; //push eax op_push(REG_EAX); } //fild dword ptr[esp] op_fld_ptr_esp(DEF_LONG); //sub esp,4 op_sub_esp(4); } else{ //符号なし //pop eax op_pop(REG_EAX); //push 0 op_push_V(0); //push eax op_push(REG_EAX); //fild qword ptr[esp] OpBuffer[obp++]=(char)0xDF; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; } //fstp qword ptr[esp] OpBuffer[obp++]=(char)0xDD; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else SetError(9,NULL,cp); } void ChangeTypeToSingle(int OldType){ //現在のスタックの内容をfloat型に変換する //NumOpeの直後専用 if(OldType==DEF_SINGLE) return; else if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] op_fld_ptr_esp(DEF_DOUBLE); //add esp,4 op_add_esp(4); //fstp dword ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //64ビット整数型 //fild qword ptr[esp] op_fld_ptr_esp(DEF_INT64); //add esp,4 op_add_esp(4); //fstp dword ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else if(IsWholeNumberType(OldType)){ //その他整数型 if(IsSignedType(OldType)){ //符号あり if(OldType==DEF_INTEGER || (isUnicode&&OldType==DEF_CHAR)){ //pop eax op_pop(REG_EAX); //movsx eax,ax OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0xBF; OpBuffer[obp++]=(char)0xC0; //push eax op_push(REG_EAX); } else if(OldType==DEF_SBYTE || (isUnicode==false&&OldType==DEF_CHAR)){ //pop eax op_pop(REG_EAX); //movsx eax,al OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0xBE; OpBuffer[obp++]=(char)0xC0; //push eax op_push(REG_EAX); } //fild dword ptr[esp] op_fld_ptr_esp(DEF_LONG); } else{ //符号なし //fild dword ptr[esp] op_fld_ptr_esp(DEF_LONG); } //fstp dword ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else SetError(9,NULL,cp); } void ChangeTypeToInt64(int OldType){ //現在のスタックの内容をInt64型に変換する //NumOpeの直後専用 if(Is64Type(OldType)) return; else if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] op_fld_ptr_esp(DEF_DOUBLE); //fistp qword ptr[esp] op_fistp_ptr_esp( sizeof(_int64) ); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 op_sub_esp(4); //fistp qword ptr[esp] op_fistp_ptr_esp( sizeof(_int64) ); } else if(IsWholeNumberType(OldType)){ //その他整数 if(IsSignedType(OldType)){ //符号あり //pop eax op_pop(REG_EAX); //cdq op_cdq(); //push edx op_push(REG_EDX); //push eax op_push(REG_EAX); } else{ //符号なし //pop eax op_pop(REG_EAX); //push 0 op_push_V(0); //push eax op_push(REG_EAX); } } else SetError(9,NULL,cp); } void ChangeTypeToLong(int OldType){ //現在のスタックの内容をLong型に変換する //NumOpeの直後専用 if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] op_fld_ptr_esp(DEF_DOUBLE); //add esp,4 op_add_esp(4); //fistp dword ptr[esp] op_fistp_ptr_esp( sizeof(long) ); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //fistp dword ptr[esp] op_fistp_ptr_esp( sizeof(long) ); } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //pop eax op_pop(REG_EAX); //add esp,4 op_add_esp(4); //push eax op_push(REG_EAX); } } void ChangeTypeToInteger(int OldType){ //現在のスタックの内容をInteger型に変換する if(OldType==DEF_BOOLEAN|| OldType==DEF_BYTE|| OldType==DEF_WORD||OldType==DEF_INTEGER || (isUnicode&&OldType==DEF_CHAR)) return; else if(OldType==DEF_SBYTE || (isUnicode==false&&OldType==DEF_CHAR)){ //pop eax op_pop(REG_EAX); //movsx eax,al OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0xBE; OpBuffer[obp++]=(char)0xC0; //push eax op_push(REG_EAX); } else{ ChangeTypeToLong(OldType); //pop eax op_pop(REG_EAX); //and eax,0000FFFFh OpBuffer[obp++]=(char)0x25; *((long *)(OpBuffer+obp))=0x0000FFFF; obp+=sizeof(long); //push eax op_push(REG_EAX); } } void ChangeTypeToByte(int OldType){ //現在のスタックの内容をbyte型に変換する if(OldType==DEF_BYTE||OldType==DEF_SBYTE || (isUnicode==false&&OldType==DEF_CHAR)) return; ChangeTypeToLong(OldType); //pop eax op_pop(REG_EAX); //and eax,000000FFh OpBuffer[obp++]=(char)0x25; *((long *)(OpBuffer+obp))=0x000000FF; obp+=sizeof(long); //push eax op_push(REG_EAX); } void RestoreDefaultRegisterFromStackMemory( int type ){ //現在のスタックの内容を実数レジスタに保存する //NumOpeの直後専用 if(type==DEF_DOUBLE){ //fld qword ptr[esp] op_fld_ptr_esp(DEF_DOUBLE); //add esp,8 op_add_esp(8); } else if(type==DEF_SINGLE){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //add esp,4 op_add_esp(4); } else if( Is64Type( type ) ){ //pop eax op_pop(REG_EAX); //pop edx op_pop(REG_EDX); } else{ //pop eax op_pop(REG_EAX); } } void SetVariableFromEax(int VarType,int CalcType,RELATIVE_VAR *pRelativeVar){ ///////////////////////////////////////////////// // eaxの内容を変数にコピーするコードを抽出 ///////////////////////////////////////////////// if(VarType==DEF_BOOLEAN){ //bool SetBooleanVariable(CalcType,pRelativeVar); } else if( IsRealNumberType( VarType ) ){ // Double/Single型変数へレジスタの値を代入 SetRealVariable(VarType, CalcType, pRelativeVar); } else if( IsWholeNumberType( VarType ) || VarType == DEF_OBJECT ){ int typeSize = GetTypeSize( VarType, -1 ); //整数変数へraxの値を格納する SetWholeVariable( typeSize, CalcType, pRelativeVar ); } else{ SetError(300,NULL,cp); } } void OpcodeCalc(char *Command){ int i,i2,i3; char variable[VN_SIZE]; ////////////////////////////////////// // インクリメント・デクリメント ////////////////////////////////////// for(i=0;;i++){ if(Command[i]=='\"'){ //ダブルクォートは不正なのでエラー扱い variable[i]=0; SetError(3,variable,cp); return; } if(Command[i]=='('){ i2=GetStringInPare(variable+i,Command+i); i+=i2-1; continue; } if(Command[i]=='['){ i2=GetStringInBracket(variable+i,Command+i); i+=i2-1; continue; } if(Command[i]=='\0'){ /////////////////////////////////// // インクリメント・デクリメント /////////////////////////////////// if(i>2){ if(Command[i-2]=='+'&&Command[i-1]=='+'){ //インクリメント variable[i-2]=0; IncDec(CALC_ADDITION,variable,"1"); return; } else if(Command[i-2]=='-'&&Command[i-1]=='-'){ //デクリメント variable[i-2]=0; IncDec(CALC_SUBTRACTION,variable,"1"); return; } } //先端部分の識別子をエラーキーワードにする for(i=0;;i++){ if(!IsVariableChar(Command[i])){ variable[i]=0; break; } variable[i]=Command[i]; } if(GetVarType(variable,Type(),0)){ //変数リストに該当したとき SetError(1,NULL,cp); } else{ if(GetConstHash(variable)){ //定数リストに該当したとき SetError(1,NULL,cp); } else{ //変数リスト、定数リストに該当しないとき SetError(3,variable,cp); } } return; } i2=GetCalcId(Command+i,&i3); if(i2){ variable[i]=0; if(Command[i]=='=') break; if(Command[i+1+i3]=='='){ IncDec(i2,variable,Command+i+1+i3+1); return; } } variable[i]=Command[i]; } if(Command[i+1]=='\0'){ SetError(1,NULL,cp); return; } /////////////////////////////////////////////////////////////// // インデクサのsetアクセサ([]=演算子のオーバーロードに対応) /////////////////////////////////////////////////////////////// char ObjName[VN_SIZE],array_element[VN_SIZE]; GetArrayElement(variable,ObjName,array_element); if(array_element[0]){ Type varType; if( GetVarType(ObjName,varType,0) && varType.IsObject() ){ char temporary[VN_SIZE]; sprintf(temporary,"%s.%c%c%c",ObjName,1,ESC_OPERATOR,CALC_ARRAY_SET); char temp2[VN_SIZE]; sprintf(temp2,"%s,%s",array_element,Command+i+1); int idProc; void *pProc; idProc=GetProc(temporary,(void **)&pProc); if(idProc){ CallProc(idProc,pProc,temporary,temp2,Type()); return; } } } if( lstrcmpi( variable, "This" ) == 0 ){ SetError(133,NULL,cp); return; } //////////////////////////////////////// // 変数のタイプ型を識別して、演算を行う //////////////////////////////////////// Type varType; //型を識別 if( !GetVarType(variable,varType,false) ){ // プロパティ用のメソッドを呼び出す if(!CallPropertyMethod( variable, Command+i+1, Type() )){ //エラーを表示 GetVarType(variable,varType,true); } return; } extern LONG_PTR ProcPtr_BaseIndex; if(varType.IsProcPtr()) ProcPtr_BaseIndex=varType.GetIndex(); else ProcPtr_BaseIndex=-1; RELATIVE_VAR VarRelativeVar; if( varType.IsStruct() ){ //代入コピーに備える //変数アドレスを取得 if(!GetVarOffsetReadWrite( variable, &VarRelativeVar, varType)) return; SetVarPtrToEax(&VarRelativeVar); //push eax op_push(REG_EAX); } //NumOpe...(スタックに答えが格納される) BOOL bCalcUseHeap; Type calcType; if( !NumOpe(Command+i+1,varType,calcType,&bCalcUseHeap) ){ return; } //変数アドレスを取得 if(!GetVarOffsetReadWrite( variable, &VarRelativeVar, varType)) return; if(varType.GetBasicType()&FLAG_PTR){ SetError(14,variable,cp); return; } if( varType.IsStruct() ){ //構造体インスタンスへの代入 SetStructVariable(varType,calcType,bCalcUseHeap); return; } if( calcType.IsObject() && !calcType.Equals( varType ) ){ bool isUpCast = false; if( varType.IsObject() ){ if( varType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){ isUpCast = true; } } if( !isUpCast ){ //キャスト演算子のオーバーロードに対応する CallCastOperatorProc(calcType,bCalcUseHeap,varType); } } if( varType.IsObject() && Smoothie::Meta::blittableTypes.IsExist( calcType ) ){ // Blittable型をオブジェクトとして扱う vector userProcs; Smoothie::Meta::blittableTypes.GetClass( calcType ).EnumStaticMethod( "_Create", userProcs ); if( userProcs.size() != 1 ){ SetError(); return; } UserProc *pUserProc = userProcs[0]; // call System.[TypeClass]._Create op_call( pUserProc ); // push eax op_push( REG_EAX ); calcType = pUserProc->ReturnType(); } ///////////////////////////////// // 右辺、左辺の型チェックを行う ///////////////////////////////// CheckDifferentType(varType,calcType,0,0); ///////////////////////////////////////////////// // スタックの内容を変数にコピーするコードを抽出 ///////////////////////////////////////////////// //eax、edx:eax、またはst(0)にスタック上のデータを取り出す RestoreDefaultRegisterFromStackMemory( calcType.GetBasicType() ); SetVariableFromEax(varType.GetBasicType(),calcType.GetBasicType(),&VarRelativeVar); }