#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, "__unsafe_call" ) == 0 ) return FUNC_UNSAFE_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_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 *name ){ extern int cp; const UserProc *pUserProc; extern LONG_PTR ProcPtr_BaseIndex; if(ProcPtr_BaseIndex!=-1){ //左辺の型にのっとり、オーバーロードを解決 std::vector subs; GetOverloadSubHash( name, subs ); if( subs.size() == 0 ){ SetError(27,name,cp); return; } //オーバーロードを解決 pUserProc=OverloadSolution(name,subs,compiler.GetObjectModule().meta.GetProcPointers()[ProcPtr_BaseIndex]->Params(), Type() ); if(!pUserProc){ SetError(27,name,cp); return; } } else{ pUserProc=GetSubHash(name); if(!pUserProc){ SetError(27,name,cp); return; } } if( pUserProc->IsVirtual() ){ /////////////////////////////// // 仮想関数の場合 // thisポインタをrcxにコピー /////////////////////////////// const CClass *pobj_c; char ObjectName[VN_SIZE]; ReferenceKind referenceKind; SplitObjectName(name,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; } //仮想関数(オブジェクトメソッド) //pObj->func_table->func1 // ->func2 // ->func3 //mov r11,qword ptr[rcx] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE); int i2 = pobj_c->GetFuncNumInVtbl( pUserProc ); //mov rax,qword ptr[r11+func_index] if(i2*PTR_SIZE<=0x7F){ compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,i2*PTR_SIZE,MOD_BASE_DISP8); } else{ compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,i2*PTR_SIZE,MOD_BASE_DISP32); } } else{ //一般の関数 //mov rax,ProcAddr compiler.codeGenerator.op_addressof( REG_RAX, pUserProc ); } pUserProc->Using(); } 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_unsafe_call( const char *paramsStr, Type &resultType, bool isCallOn ) { if( isCallOn ) { int i = 0; char methodPtrParamStr[8192]; GetOneParameter( paramsStr, i, methodPtrParamStr ); UnsafeCall( methodPtrParamStr, paramsStr + i ); } resultType = UserProc::CompilingUserProc().ReturnType(); } 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, Type &resultType, bool isCallOn ){ switch(FuncNum){ case FUNC_LEN: if( isCallOn ) Opcode_Func_Len(Parameter); resultType.SetBasicType( DEF_LONG ); break; case FUNC_ADDRESSOF: if( isCallOn ) Opcode_Func_AddressOf(Parameter); resultType.SetBasicType( DEF_PTR_VOID ); 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_UNSAFE_CALL: Opcode_Func_unsafe_call( Parameter, resultType, 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; }