#include "stdafx.h" #include #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" int GetFunctionFromName(char *FuncName){ 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, "_System_GetNowScopeCatchAddresses" ) == 0 )return FUNC_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS; if( lstrcmpi( FuncName, "_System_GetNowScopeFinallyAddresses" ) == 0 )return FUNC_SYSTEM_GET_NOW_SCOPE_FINALLY_ADDRESS; if( lstrcmpi( FuncName, "_System_GetBp" ) == 0 ) return FUNC_SYSTEM_GET_BP; if( lstrcmpi( FuncName, "_System_GetSp" ) == 0 ) return FUNC_SYSTEM_GET_SP; 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_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()); 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 rax,TypeSize compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,typeSize); return; } 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; SetVarPtrToReg(REG_RCX,&RelativeVar); //参照タイプが整合しているかをチェック if( !( type.IsObject() && referenceKind == RefDot || type.IsObjectPtr() && referenceKind == RefPointer ) ) { SetError(104,ObjectName,cp); } if(type.IsObjectPtr()){ //mov rcx,qword ptr[rcx] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE); } } } else{ InClassMember: //自身のオブジェクトのThisポインタをrcxにコピー SetThisPtrToReg(REG_RCX); pobj_c=compiler.pCompilingClass; } int vtblIndex; if( pobj_c->IsInterface() ) { // インターフェイスメソッド int offset_vtbl = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__vtbl" ); // vtblのポインタを取得 //mov r11,qword ptr[rcx+offset_vtbl] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,offset_vtbl,MOD_BASE_DISP8); int offset_this = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__this" ); // インターフェイスの場合は更に__thisを取得する //mov rcx,qword ptr[rcx+offset_this] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,offset_this,MOD_BASE_DISP8); int vtblMasterListIndex; pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex ); if( vtblMasterListIndex != 0 ) { SetError(); } } else { //仮想関数(オブジェクトメソッド) // pObj -> vtbl_master_list -> vtbl1 -> func1 // -> func2 // -> func3 // -> vtbl2 -> func1 // -> func2 // -> func3 int vtblMasterListIndex; pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex ); // vtblマスターリストのポインタを取得 //mov r11,qword ptr[rcx] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE); // vtblのポインタを取得 //mov r11,dword ptr[r11+vtblMasterListIndex] compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_R11, REG_R11, vtblMasterListIndex, MOD_BASE_DISP32 ); } //mov rax,qword ptr[r11+func_index] if( vtblIndex * PTR_SIZE <= 0x7F ) { compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP8); } else { compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP32); } } else{ //一般の関数 //mov rax,ProcAddr compiler.codeGenerator.op_addressof( REG_RAX, &userProc ); } userProc.Using(); } void Opcode_CreateDelegate( const CClass &dgClass, const char *methodInstanceName, const UserProc &userProc ) { ///////////////////////////////////////////////////////////////// // 関数ポインタをpush ///////////////////////////////////////////////////////////////// //mov rax,AddressOf _Opcode_Func_AddressOf( methodInstanceName, userProc ); if( userProc.GetMethod().IsDynamic() ) { //mov rdx,rax compiler.codeGenerator.op_mov_RR( REG_RDX, REG_RAX ); pobj_BlockReg->lock( REG_RDX ); ///////////////////////////////////////////////////////////////// // オブジェクト ポインタを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; } SetVarPtrToReg( REG_RAX, &relativeVar ); //mov rcx,dword ptr[rax] compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RCX, REG_RAX, 0, MOD_BASE ); pobj_BlockReg->unlock( REG_RDX ); } else { //mov rcx,rax compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX ); } ///////////////////////////////////////////////////////////////// // call _CreateDynamicDelegate/_CreateStaticDelegate ///////////////////////////////////////////////////////////////// std::vector subs; if( userProc.GetMethod().IsDynamic() ) { dgClass.GetStaticMethods().Enum( "_CreateDynamicDelegate", subs ); } else { dgClass.GetStaticMethods().Enum( "_CreateStaticDelegate", subs ); } // call _CreateDynamicDelegate 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( isCallOn && baseType.IsDelegate() ) { // コード生成を伴う場合はエラーチェックを行う if( !pUserProc->Params().Equals( *pBaseParams ) || !pUserProc->ReturnType().Equals( baseType.GetClass().GetDelegate().ReturnType() ) ) { if( baseType.IsDelegate() ) { SetError(67, name, cp ); } else { SetError(66, name, cp ); } } } 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 rax,size compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,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(); SetVarPtrToReg(REG_RAX,&RelativeVar); // TODO: 取り除く(この動きはObjPtrに託す) /* if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){ //参照をオブジェクトポインタに変更 //mov rax,qword ptr[rax] compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE ); SetError(-120,NULL,cp); }*/ } 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(); SetVarPtrToReg(REG_RAX,&RelativeVar); if( lstrcmpi( Parameter, "This" )==0 ){ // Thisの場合は特別にオブジェクトポインタが返ってくるので、何もせずに抜ける } else if( beforeType == DEF_OBJECT ){ //参照をオブジェクトポインタに変更 //mov rax,qword ptr[rax] compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 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_System_Get_Bp() { //mov rax,rbp compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RBP); } void Opcode_Func_System_Get_Sp() { //mov rax,rsp compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RSP); } void Opcode_Func_GetPtrData( const char *Parameter, const int type ){ int reg=REG_RAX; Type tempType; if( !NumOpe(®,Parameter,Type(),tempType) ){ return; } if(!tempType.IsWhole()){ SetError(11,Parameter,cp); return; } if(type==DEF_DOUBLE){ //movlpd xmm0,qword ptr[rax] compiler.codeGenerator.op_movlpd_RM(REG_XMM0,REG_RAX,0,MOD_BASE); } else if(type==DEF_SINGLE){ //movss xmm0,dword ptr[rax] compiler.codeGenerator.op_movss_RM(REG_XMM0,REG_RAX,0,MOD_BASE); } else{ //mov rax,ptr[rax] compiler.codeGenerator.op_mov_RM(Type(type).GetSize(),REG_RAX,REG_RAX,0,MOD_BASE); } } bool Opcode_CallFunc( const char *Parameter, const int FuncNum, const Type &baseType, Type &resultType, bool isCallOn ) { switch(FuncNum){ 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_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS: if( isCallOn ) Exception::Opcode_Func_System_GetNowScopeCatchAddress(); resultType.SetBasicType( DEF_PTR_VOID ); break; case FUNC_SYSTEM_GET_NOW_SCOPE_FINALLY_ADDRESS: if( isCallOn ) Exception::Opcode_Func_System_GetNowScopeFinallyAddress(); resultType.SetBasicType( DEF_PTR_VOID ); break; case FUNC_SYSTEM_GET_BP: if( isCallOn ) Opcode_Func_System_Get_Bp(); resultType.SetBasicType( DEF_INT64 ); break; case FUNC_SYSTEM_GET_SP: if( isCallOn ) Opcode_Func_System_Get_Sp(); resultType.SetBasicType( DEF_INT64 ); 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; }