#include "stdafx.h" #include #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" int GetFunctionFromName(char *FuncName){ if( lstrcmpi( FuncName, "CUDbl" ) == 0 ) return FUNC_CUDBL; if( lstrcmpi( FuncName, "Fix" ) == 0 ) return FUNC_FIX; if( lstrcmpi( FuncName, "Len" ) == 0 ) return FUNC_LEN; if( lstrcmpi( FuncName, "AddressOf" ) == 0 ) return FUNC_ADDRESSOF; if( lstrcmpi( FuncName, "SizeOf" ) == 0 ) return FUNC_SIZEOF; if( lstrcmpi( FuncName, "VarPtr" ) == 0 ) return FUNC_VARPTR; if( lstrcmpi( FuncName, "ObjPtr" ) == 0 ) return FUNC_OBJPTR; if( lstrcmpi( FuncName, "__delegate_dynamicmethod_call" ) == 0 ) return FUNC_DELEGATE_DYNAMICMETHOD_CALL; if( lstrcmpi( FuncName, "__delegate_staticmethod_call" ) == 0 ) return FUNC_DELEGATE_STATICMETHOD_CALL; if( lstrcmpi( FuncName, "GetDouble" ) == 0 ) return FUNC_GETDOUBLE; if( lstrcmpi( FuncName, "GetSingle" ) == 0 ) return FUNC_GETSINGLE; if( lstrcmpi( FuncName, "GetQWord" ) == 0 ) return FUNC_GETQWORD; if( lstrcmpi( FuncName, "GetDWord" ) == 0 ) return FUNC_GETDWORD; if( lstrcmpi( FuncName, "GetWord" ) == 0 ) return FUNC_GETWORD; if( lstrcmpi( FuncName, "GetByte" ) == 0 ) return FUNC_GETBYTE; return 0; } void Opcode_Func_Fix(const char *lpszParms){ Type resultType; if( !NumOpe( lpszParms, Type(), resultType ) ){ return; } if( resultType.IsDouble() ){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //fnstcw word ptr[esp] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x3C, (char)0x24 ); //mov ax,word ptr[esp] compiler.codeGenerator.op_mov_RM( sizeof(short), REG_EAX, REG_ESP, 0, MOD_BASE ); //or ah,0Ch compiler.codeGenerator.PutOld( (char)0x80, (char)0xCC, (char)0x0C ); //mov word ptr[esp-2],ax compiler.codeGenerator.op_mov_MR( sizeof(short), REG_EAX, REG_ESP, -2, MOD_BASE_DISP8 ); //fldcw word ptr[esp-2] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x6C, (char)0x24, (char)0xFE ); //fistp dword ptr[esp+4] compiler.codeGenerator.PutOld( (char)0xDB, (char)0x5C, (char)0x24, (char)0x04 ); //fldcw word ptr[esp] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x2C, (char)0x24 ); //add esp,4 compiler.codeGenerator.op_add_esp(4); } else if( resultType.IsSingle() ){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 compiler.codeGenerator.op_sub_esp(4); //fnstcw word ptr[esp] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x3C, (char)0x24 ); //mov ax,word ptr[esp] compiler.codeGenerator.op_mov_RM( sizeof(short), REG_EAX, REG_ESP, 0, MOD_BASE ); //or ah,0Ch compiler.codeGenerator.PutOld( (char)0x80, (char)0xCC, (char)0x0C ); //mov word ptr[esp-2],ax compiler.codeGenerator.op_mov_MR( sizeof(short), REG_EAX, REG_ESP, -2, MOD_BASE_DISP8 ); //fldcw word ptr[esp-2] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x6C, (char)0x24, (char)0xFE ); //fistp dword ptr[esp+4] compiler.codeGenerator.PutOld( (char)0xDB, (char)0x5C, (char)0x24, (char)0x04 ); //fldcw word ptr[esp] compiler.codeGenerator.PutOld( (char)0xD9, (char)0x2C, (char)0x24 ); //add esp,4 compiler.codeGenerator.op_add_esp(4); } else if( resultType.Is64() ){ //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); } //pop eax compiler.codeGenerator.op_pop(REG_EAX); } void Opcode_Func_CUDbl(const char *Parameter){ Type resultType; if( !NumOpe(Parameter,Type(),resultType) ){ return; } ChangeTypeToLong(resultType.GetBasicType()); //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.op_fld_ptr_esp(DEF_INT64); //add esp,8 compiler.codeGenerator.op_add_esp(8); } void Opcode_Func_Len(const char *Parameter){ BOOL bArrayHead; const char *tempParm=Parameter; char temporary[VN_SIZE]; char temp2[32]; Type type; if( !GetVarType(Parameter,type,0) ){ sprintf(temporary,"_System_DummyStr2=%s",Parameter); OpcodeCalc(temporary); lstrcpy(temp2,"_System_DummyStr2"); tempParm=temp2; type.SetType( DEF_OBJECT, compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr() ); } if( type.IsStringClass() ){ //Stringオブジェクトの場合 sprintf(temporary,"%s.Length",tempParm); int reg=REG_RAX; NumOpe(temporary,Type(),Type()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); return; } Subscripts subscripts; RELATIVE_VAR RelativeVar; if(!GetVarOffsetReadOnly(tempParm,&RelativeVar,type,&subscripts)) return; if(type.GetBasicType()&FLAG_PTR){ type.SetBasicType( type.GetBasicType() & ( ~FLAG_PTR ) ); bArrayHead=1; } else bArrayHead=0; int typeSize = type.GetSize(); if(bArrayHead) typeSize*=JumpSubScripts(subscripts); //mov eax,typeSize compiler.codeGenerator.op_mov_RV( REG_EAX, typeSize ); } void _Opcode_Func_AddressOf( const char *methodInstanceName, const UserProc &userProc ) { if( userProc.IsVirtual() ){ /////////////////////////////// // 仮想関数の場合 // thisポインタをrcxにコピー /////////////////////////////// const CClass *pobj_c; char ObjectName[VN_SIZE]; ReferenceKind referenceKind; SplitObjectName( methodInstanceName, ObjectName, referenceKind ); if(ObjectName[0]){ if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember; else{ RELATIVE_VAR RelativeVar; Type type; if(!GetVarOffsetReadOnly(ObjectName,&RelativeVar,type)) return; SetVarPtrToEax(&RelativeVar); //mov ecx,eax compiler.codeGenerator.op_mov_RR(REG_ECX,REG_EAX); //参照タイプが整合しているかをチェック if( !( type.IsObject() && referenceKind == RefDot || type.IsObjectPtr() && referenceKind == RefPointer ) ) { SetError(104,ObjectName,cp); } if(type.IsObjectPtr()){ //mov ecx,dword ptr[ecx] compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_ECX,0,MOD_BASE); } } } else{ InClassMember: //自身のオブジェクトのThisポインタをrcxにコピー SetThisPtrToReg(REG_RCX); pobj_c=compiler.pCompilingClass; } //仮想関数(オブジェクトメソッド) //pObj->func_table->func1 // ->func2 // ->func3 //mov edx,dword ptr[ecx] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EDX, REG_ECX, 0, MOD_BASE ); int i2 = pobj_c->GetFuncNumInVtbl( &userProc ); //mov eax,dword ptr[edx+func_index] if(i2*PTR_SIZE<=0x7F){ compiler.codeGenerator.op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP8); } else{ compiler.codeGenerator.op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP32); } } else{ //一般の関数 //mov eax,ProcAddr compiler.codeGenerator.op_addressof( REG_EAX, &userProc ); } userProc.Using(); } void Opcode_CreateDelegate( const CClass &dgClass, const char *methodInstanceName, const UserProc &userProc ) { ///////////////////////////////////////////////////////////////// // 関数ポインタをpush ///////////////////////////////////////////////////////////////// //push AddressOf(userProc) _Opcode_Func_AddressOf( methodInstanceName, userProc ); compiler.codeGenerator.op_push( REG_EAX ); ///////////////////////////////////////////////////////////////// // オブジェクト ポインタをpush ///////////////////////////////////////////////////////////////// // オブジェクト名を取得 char objectName[VN_SIZE]; char memberName[VN_SIZE]; char *thisPtrName = "This"; Type type; if( SplitMemberName( methodInstanceName, objectName, memberName ) ) { if( GetVarType( objectName, type, false ) ) { thisPtrName = objectName; } } // オブジェクト ポインタを取得 RELATIVE_VAR relativeVar; GetVarOffsetReadOnly( thisPtrName, &relativeVar, type ); if( !type.IsObject() ) { extern int cp; SetError(1,NULL,cp); return; } SetVarPtrToEax( &relativeVar ); //mov eax,dword ptr[eax] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE ); //push eax compiler.codeGenerator.op_push( REG_EAX ); ///////////////////////////////////////////////////////////////// // call _System_CreateSimpleDynamicDelegate ///////////////////////////////////////////////////////////////// std::vector subs; dgClass.GetStaticMethods().Enum( "_CreateDelegate", subs ); // call _System_CreateSimpleDynamicDelegate compiler.codeGenerator.op_call( subs[0] ); } void Opcode_Func_AddressOf( const char *name, const Type &baseType, bool isCallOn, Type &resultType ){ extern int cp; const UserProc *pUserProc; const Parameters *pBaseParams = NULL; if( baseType.IsProcPtr() ) { // 左辺で関数ポインタを要求されているとき pBaseParams = &compiler.GetObjectModule().meta.GetProcPointers()[baseType.GetIndex()]->Params(); } else if( baseType.IsDelegate() ) { // 左辺でデリゲートを要求されているとき pBaseParams = &baseType.GetClass().GetDelegate().Params(); } if( pBaseParams ) { //左辺の型にのっとり、オーバーロードを解決 std::vector subs; GetOverloadSubHash( name, subs ); if( subs.size() == 0 ){ SetError(27,name,cp); return; } //オーバーロードを解決 pUserProc=OverloadSolution( name, subs, *pBaseParams, Type() ); if(!pUserProc){ SetError(27,name,cp); return; } } else{ pUserProc=GetSubHash(name); if(!pUserProc){ SetError(27,name,cp); return; } } if( baseType.IsDelegate() ) { if( isCallOn ) { // デリゲートのとき Opcode_CreateDelegate( baseType.GetClass(), name, *pUserProc ); } resultType = baseType; } else { if( isCallOn ) { // 関数ポインタのとき _Opcode_Func_AddressOf( name, *pUserProc ); } resultType.SetBasicType( DEF_PTR_VOID ); } } void Opcode_Func_SizeOf( const string &typeName ){ Type tempType; if( !compiler.StringToType( typeName, tempType ) ){ SetError(3,typeName,cp); return; } int typeSize = ( tempType.IsObject() ) ? tempType.GetClass().GetSize() : tempType.GetSize(); //mov eax,size compiler.codeGenerator.op_mov_RV( REG_EAX, typeSize ); } void Opcode_Func_VarPtr( const char *Parameter, Type &resultType, bool isCallOn ){ if( isCallOn == false ){ // 戻り値の型を取得するだけ //変数のアドレスを取得 if(!GetVarType( Parameter, resultType, true )) return; resultType.PtrLevelUp(); return; } RELATIVE_VAR RelativeVar; //変数のアドレスを取得 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return; int beforeType = resultType.GetBasicType(); resultType.PtrLevelUp(); SetVarPtrToEax(&RelativeVar); } void Opcode_Func_ObjPtr( const char *Parameter, Type &resultType, bool isCallOn ){ if( isCallOn == false ){ // 戻り値の型を取得するだけ //変数のアドレスを取得 if(!GetVarType( Parameter, resultType, true )) return; resultType.PtrLevelUp(); return; } RELATIVE_VAR RelativeVar; //変数のアドレスを取得 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return; int beforeType = resultType.GetBasicType(); resultType.PtrLevelUp(); SetVarPtrToEax(&RelativeVar); if( lstrcmpi( Parameter, "This" )==0 ){ // Thisの場合は特別にオブジェクトポインタが返ってくるので、何もせずに抜ける } else if( beforeType == DEF_OBJECT ){ //参照をオブジェクトポインタに変更 //mov eax,dword ptr[eax] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE ); } else{ SetError(134,NULL,cp ); } } void Opcode_Func_delegate_call( const char *paramsStr, Type &resultType, bool isDynamicCall, bool isCallOn ) { if( isCallOn ) { int i = 0; char methodPtrParamStr[VN_SIZE]; i = GetOneParameter( paramsStr, i, methodPtrParamStr ); char objPtrValueStr[VN_SIZE]; if( isDynamicCall ) { i = GetOneParameter( paramsStr, i, objPtrValueStr ); } Opcode_CallDelegate( compiler.pCompilingClass->GetDelegate(), methodPtrParamStr, objPtrValueStr, paramsStr + i ); } resultType = UserProc::CompilingUserProc().ReturnType(); } void Opcode_Func_GetPtrData(const char *Parameter,const int type){ Type tempType; if( !NumOpe(Parameter,Type(),tempType) ){ return; } if(!tempType.IsWhole()){ SetError(11,Parameter,cp); return; } ChangeTypeToLong(tempType.GetBasicType()); if(type==DEF_DOUBLE){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //fld qword ptr[eax] compiler.codeGenerator.PutOld( (char)0xDD, (char)0x00 ); } else if(type==DEF_SINGLE||type==DEF_DWORD){ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov eax,dword ptr[eax] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE ); } else if(type==DEF_QWORD){ //pop ecx compiler.codeGenerator.op_pop(REG_ECX); //mov eax,dword ptr[ecx] compiler.codeGenerator.op_mov_RM(sizeof(long),REG_EAX,REG_ECX,0,MOD_BASE); //mov edx,dword ptr[ecx+sizeof(long)] compiler.codeGenerator.op_mov_RM(sizeof(long),REG_EDX,REG_ECX,sizeof(long),MOD_BASE_DISP8); } else if(type==DEF_WORD){ //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //xor eax,eax compiler.codeGenerator.op_xor_RR(REG_EAX); //mov ax,word ptr[ebx] compiler.codeGenerator.op_mov_RM( sizeof(short), REG_EAX, REG_EBX, 0, MOD_BASE ); } else if(type==DEF_BYTE){ //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //xor eax,eax compiler.codeGenerator.op_xor_RR(REG_EAX); //mov al,byte ptr[ebx] compiler.codeGenerator.op_mov_RM( sizeof(char), REG_EAX, REG_EBX, 0, MOD_BASE ); } } bool Opcode_CallFunc( const char *Parameter, const int FuncNum, const Type &baseType, Type &resultType, bool isCallOn ) { switch(FuncNum){ case FUNC_FIX: if( isCallOn ) Opcode_Func_Fix(Parameter); resultType.SetBasicType( DEF_LONG ); break; case FUNC_CUDBL: if( isCallOn ) Opcode_Func_CUDbl(Parameter); resultType.SetBasicType( DEF_DOUBLE ); break; case FUNC_LEN: if( isCallOn ) Opcode_Func_Len(Parameter); resultType.SetBasicType( DEF_LONG ); break; case FUNC_ADDRESSOF: Opcode_Func_AddressOf( Parameter, baseType, isCallOn, resultType ); break; case FUNC_SIZEOF: if( isCallOn ) Opcode_Func_SizeOf(Parameter); resultType.SetBasicType( DEF_LONG ); break; case FUNC_VARPTR: Opcode_Func_VarPtr( Parameter, resultType, isCallOn ); break; case FUNC_OBJPTR: Opcode_Func_ObjPtr( Parameter, resultType, isCallOn ); break; case FUNC_DELEGATE_DYNAMICMETHOD_CALL: Opcode_Func_delegate_call( Parameter, resultType, true, isCallOn ); break; case FUNC_DELEGATE_STATICMETHOD_CALL: Opcode_Func_delegate_call( Parameter, resultType, false, isCallOn ); break; case FUNC_GETDOUBLE: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DOUBLE); resultType.SetBasicType( DEF_DOUBLE ); break; case FUNC_GETSINGLE: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_SINGLE); resultType.SetBasicType( DEF_SINGLE ); break; case FUNC_GETQWORD: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_QWORD); resultType.SetBasicType( DEF_QWORD ); break; case FUNC_GETDWORD: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DWORD); resultType.SetBasicType( DEF_DWORD ); break; case FUNC_GETWORD: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_WORD); resultType.SetBasicType( DEF_WORD ); break; case FUNC_GETBYTE: if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_BYTE); resultType.SetBasicType( DEF_BYTE ); break; default: return false; } return true; }