#include "stdafx.h" #include #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" void ChangeTypeToDouble_ToFpuReg(int OldType){ //現在のスタックの内容を実数レジスタに保存する //NumOpeの直後専用 if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //add esp,8 compiler.codeGenerator.op_add_esp(8); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //add esp,4 compiler.codeGenerator.op_add_esp(4); } else if(OldType==DEF_LONG){ //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,4 compiler.codeGenerator.op_add_esp(4); } else if(OldType==DEF_DWORD){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //push 0 compiler.codeGenerator.op_push_V(0); //push eax compiler.codeGenerator.op_push(REG_EAX); //fild qword ptr[esp] compiler.codeGenerator.PutOld( (char)0xDF, (char)0x2C, (char)0x24 ); //add esp,8 compiler.codeGenerator.op_add_esp(8); } } void ChangeTypeToDouble(int OldType){ //現在のスタックの内容をdouble型に変換する //NumOpeの直後専用 if(OldType==DEF_DOUBLE) return; else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 compiler.codeGenerator.op_sub_esp(4); //fstp qword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP ); } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //64ビット整数型 //fild qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64); //fstp qword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP ); } else if(IsWholeNumberType(OldType)){ //その他整数型 if(IsSignedType(OldType)){ //符号あり if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //movsx eax,ax compiler.codeGenerator.op_movsx_R32R16( REG_EAX ); //push eax compiler.codeGenerator.op_push(REG_EAX); } else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //movsx eax,al compiler.codeGenerator.op_movsx_R32R8( REG_EAX ); //push eax compiler.codeGenerator.op_push(REG_EAX); } //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //sub esp,4 compiler.codeGenerator.op_sub_esp(4); } else{ //符号なし //pop eax compiler.codeGenerator.op_pop(REG_EAX); //push 0 compiler.codeGenerator.op_push_V(0); //push eax compiler.codeGenerator.op_push(REG_EAX); //fild qword ptr[esp] compiler.codeGenerator.PutOld( (char)0xDF, (char)0x2C, (char)0x24 ); } //fstp qword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP ); } 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] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //add esp,4 compiler.codeGenerator.op_add_esp(4); //fstp dword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP ); } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //64ビット整数型 //fild qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64); //add esp,4 compiler.codeGenerator.op_add_esp(4); //fstp dword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP ); } else if(IsWholeNumberType(OldType)){ //その他整数型 if(IsSignedType(OldType)){ //符号あり if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //movsx eax,ax compiler.codeGenerator.op_movsx_R32R16( REG_EAX ); //push eax compiler.codeGenerator.op_push(REG_EAX); } else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //movsx eax,al compiler.codeGenerator.op_movsx_R32R8( REG_EAX ); //push eax compiler.codeGenerator.op_push(REG_EAX); } //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); } else{ //符号なし //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); } //fstp dword ptr[esp] compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP ); } else SetError(9,NULL,cp); } void ChangeTypeToInt64(int OldType){ //現在のスタックの内容をInt64型に変換する //NumOpeの直後専用 if(Is64Type(OldType)) return; else if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //fistp qword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) ); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 compiler.codeGenerator.op_sub_esp(4); //fistp qword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) ); } else if(IsWholeNumberType(OldType)){ //その他整数 if(IsSignedType(OldType)){ //符号あり //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cdq compiler.codeGenerator.op_cdq(); //push edx compiler.codeGenerator.op_push(REG_EDX); //push eax compiler.codeGenerator.op_push(REG_EAX); } else{ //符号なし //pop eax compiler.codeGenerator.op_pop(REG_EAX); //push 0 compiler.codeGenerator.op_push_V(0); //push eax compiler.codeGenerator.op_push(REG_EAX); } } else SetError(9,NULL,cp); } void ChangeTypeToLong(int OldType){ //現在のスタックの内容をLong型に変換する //NumOpeの直後専用 if(OldType==DEF_DOUBLE){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //add esp,4 compiler.codeGenerator.op_add_esp(4); //fistp dword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) ); } else if(OldType==DEF_SINGLE){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //fistp dword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) ); } else if(OldType==DEF_INT64||OldType==DEF_QWORD){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //add esp,4 compiler.codeGenerator.op_add_esp(4); //push eax compiler.codeGenerator.op_push(REG_EAX); } } void ChangeTypeToInteger(int OldType){ //現在のスタックの内容をInteger型に変換する if(OldType==DEF_BOOLEAN|| OldType==DEF_BYTE|| OldType==DEF_WORD||OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)) return; else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //movsx eax,al compiler.codeGenerator.op_movsx_R32R8( REG_EAX ); //push eax compiler.codeGenerator.op_push(REG_EAX); } else{ ChangeTypeToLong(OldType); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //and eax,0000FFFFh compiler.codeGenerator.op_and_RV( REG_EAX, 0x0000FFFF ); //push eax compiler.codeGenerator.op_push(REG_EAX); } } void ChangeTypeToByte(int OldType){ //現在のスタックの内容をbyte型に変換する if(OldType==DEF_BYTE||OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)) return; ChangeTypeToLong(OldType); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //and eax,000000FFh compiler.codeGenerator.op_and_RV( REG_EAX, 0x000000FF ); //push eax compiler.codeGenerator.op_push(REG_EAX); } void RestoreDefaultRegisterFromStackMemory( int type ){ //現在のスタックの内容を実数レジスタに保存する //NumOpeの直後専用 if(type==DEF_DOUBLE){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //add esp,8 compiler.codeGenerator.op_add_esp(8); } else if(type==DEF_SINGLE){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //add esp,4 compiler.codeGenerator.op_add_esp(4); } else if( Is64Type( type ) ){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //pop edx compiler.codeGenerator.op_pop(REG_EDX); } else{ //pop eax compiler.codeGenerator.op_pop(REG_EAX); } } void SetVariableFromEax( const Type &varType,int CalcType,RELATIVE_VAR *pRelativeVar){ ///////////////////////////////////////////////// // eaxの内容を変数にコピーするコードを抽出 ///////////////////////////////////////////////// if( varType.IsBoolean() ) { //bool SetBooleanVariable(CalcType,pRelativeVar); } else if( varType.IsReal() ) { // Double/Single型変数へレジスタの値を代入 SetRealVariable(varType.GetBasicType(), CalcType, pRelativeVar); } else if( varType.IsWhole() || varType.IsObject() ) { int typeSize = varType.GetSize(); //整数変数へraxの値を格納する SetWholeVariable( typeSize, CalcType, pRelativeVar ); } else{ SetError(300,NULL,cp); } } void OpcodeCalc( const 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( compiler.GetObjectModule().meta.GetGlobalConsts().IsExist(variable) || compiler.GetObjectModule().meta.GetGlobalConstMacros().IsExist(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(), // ベースタイプはなし Type() ); return; } } } if( lstrcmpi( variable, "This" ) == 0 ){ SetError(133,NULL,cp); return; } //////////////////////////////////////// // 変数のタイプ型を識別して、演算を行う //////////////////////////////////////// Type varType; //型を識別 if( !GetTermTypeOnlyVariable(variable,varType) ){ // プロパティ用のメソッドを呼び出す if(!CallPropertyMethod( variable, Command+i+1, Type() )){ //エラーを表示 GetVarType(variable,varType,true); } return; } RELATIVE_VAR VarRelativeVar; if( varType.IsStruct() ){ //代入コピーに備える //変数アドレスを取得 if(!GetVarOffsetReadWrite( variable, &VarRelativeVar, varType)) return; SetVarPtrToEax(&VarRelativeVar); //push eax compiler.codeGenerator.op_push(REG_EAX); } //NumOpe...(スタックに答えが格納される) BOOL bCalcUseHeap; Type calcType; if( !NumOpe(Command+i+1,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( !TermOpeOnlyVariable( variable, varType, VarRelativeVar, true ) ) { SetError(); return; } if(varType.GetBasicType()&FLAG_PTR){ SetError(14,variable,cp); return; } if( varType.IsStruct() ){ //構造体インスタンスへの代入 SetStructVariable(varType,calcType,bCalcUseHeap); return; } if( varType.IsObject() && compiler.GetObjectModule().meta.GetBlittableTypes().IsExist( calcType ) ){ // Blittable型をオブジェクトとして扱う vector userProcs; compiler.GetObjectModule().meta.GetBlittableTypes().GetClass( calcType ).GetStaticMethods().Enum( "_Create", userProcs ); if( userProcs.size() != 1 ){ SetError(); return; } const UserProc *pUserProc = userProcs[0]; // call System.[TypeClass]._Create compiler.codeGenerator.op_call( pUserProc ); // push eax compiler.codeGenerator.op_push( REG_EAX ); calcType = pUserProc->ReturnType(); } ///////////////////////////////// // 右辺、左辺の型チェックを行う ///////////////////////////////// CheckDifferentType(varType,calcType,0,0); ///////////////////////////////////////////////// // スタックの内容を変数にコピーするコードを抽出 ///////////////////////////////////////////////// //eax、edx:eax、またはst(0)にスタック上のデータを取り出す RestoreDefaultRegisterFromStackMemory( calcType.GetBasicType() ); SetVariableFromEax(varType,calcType.GetBasicType(),&VarRelativeVar); }