#include "../BasicCompiler_Common/common.h" #include "Opcode.h" int GetFunctionType(int FuncNum){ switch(FuncNum){ case FUNC_CUDBL: return DEF_DOUBLE; case FUNC_FIX: case FUNC_LEN: return DEF_LONG; case FUNC_ADDRESSOF: case FUNC_SIZEOF: case FUNC_VARPTR: return DEF_DWORD; case FUNC_GETDOUBLE: return DEF_DOUBLE; case FUNC_GETSINGLE: return DEF_SINGLE; case FUNC_GETQWORD: return DEF_QWORD; case FUNC_GETDWORD: return DEF_DWORD; case FUNC_GETWORD: return DEF_WORD; case FUNC_GETBYTE: return DEF_BYTE; } return 0; } 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,"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] op_fld_ptr_esp(DEF_DOUBLE); //fnstcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x3C; OpBuffer[obp++]=(char)0x24; //mov ax,word ptr[esp] OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; //or ah,0Ch OpBuffer[obp++]=(char)0x80; OpBuffer[obp++]=(char)0xCC; OpBuffer[obp++]=(char)0x0C; //mov word ptr[esp-2],ax OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x44; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0xFE; //fldcw word ptr[esp-2] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x6C; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0xFE; //fistp dword ptr[esp+4] OpBuffer[obp++]=(char)0xDB; OpBuffer[obp++]=(char)0x5C; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x04; //fldcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; //add esp,4 op_add_esp(4); } else if( resultType.IsSingle() ){ //fld dword ptr[esp] op_fld_ptr_esp(DEF_SINGLE); //sub esp,4 op_sub_esp(4); //fnstcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x3C; OpBuffer[obp++]=(char)0x24; //mov ax,word ptr[esp] OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; //or ah,0Ch OpBuffer[obp++]=(char)0x80; OpBuffer[obp++]=(char)0xCC; OpBuffer[obp++]=(char)0x0C; //mov word ptr[esp-2],ax OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x44; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0xFE; //fldcw word ptr[esp-2] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x6C; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0xFE; //fistp dword ptr[esp+4] OpBuffer[obp++]=(char)0xDB; OpBuffer[obp++]=(char)0x5C; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x04; //fldcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; //add esp,4 op_add_esp(4); } else if( resultType.Is64() ){ //pop eax op_pop(REG_EAX); //add esp,4 op_add_esp(4); //push eax op_push(REG_EAX); } //pop eax op_pop(REG_EAX); } void Opcode_Func_CUDbl(const char *Parameter){ Type resultType; if( !NumOpe(Parameter,Type(),resultType) ){ return; } ChangeTypeToLong(resultType.GetBasicType()); //pop eax op_pop(REG_EAX); //push 0 OpBuffer[obp++]=(char)0x6A; OpBuffer[obp++]=(char)0x00; //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 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; extern CClass *pobj_StringClass; type.SetType( DEF_OBJECT, pobj_StringClass ); } if( type.IsStringObject() ){ //Stringオブジェクトの場合 sprintf(temporary,"%s.Length",tempParm); int reg=REG_RAX; NumOpe(temporary,Type(),Type()); //pop eax op_pop(REG_EAX); return; } int SubScripts[MAX_ARRAYDIM]; 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 OpBuffer[obp++]=(char)0xB8; *((long *)(OpBuffer+obp))=typeSize; obp+=sizeof(long); } void Opcode_Func_AddressOf( const char *name ){ extern int cp; 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,House::procPointers[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にコピー /////////////////////////////// CClass *pobj_c; char ObjectName[VN_SIZE]; int RefType; SplitObjectName(name,ObjectName,&RefType); 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 op_mov_RR(REG_ECX,REG_EAX); //参照タイプが整合しているかをチェック if(type.GetBasicType()!=RefType) SetError(104,ObjectName,cp); if(type.IsObjectPtr()){ //mov ecx,dword ptr[ecx] op_mov_RM(sizeof(long),REG_ECX,REG_ECX,0,MOD_BASE); } } } else{ InClassMember: //自身のオブジェクトのThisポインタをrcxにコピー SetThisPtrToReg(REG_RCX); pobj_c=pobj_CompilingClass; } //仮想関数(オブジェクトメソッド) //pObj->func_table->func1 // ->func2 // ->func3 //mov edx,dword ptr[ecx] OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x11; int i2 = pobj_c->GetFuncNumInVtbl( pUserProc ); //mov eax,dword ptr[edx+func_index] if(i2*PTR_SIZE<=0x7F){ op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP8); } else{ op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP32); } } else{ //一般の関数 //mov eax,ProcAddr OpBuffer[obp++]=(char)0xB8; pobj_SubAddrSchedule->add(pUserProc,0); obp+=sizeof(long); } pUserProc->Using(); } void Opcode_Func_SizeOf(const char *Parameter){ LONG_PTR lpIndex; int type = GetTypeFixed(Parameter,&lpIndex); int size; if( type == DEF_OBJECT ){ CClass *pClass = (CClass *)lpIndex; size = pClass->GetSize(); } else{ size=GetTypeSize(type,lpIndex); } //mov eax,size op_mov_RV( REG_EAX, size ); } 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); if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){ //参照をオブジェクトポインタに変更 //mov eax,dword ptr[eax] op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE ); } } 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 op_pop(REG_EAX); //fld qword ptr[eax] OpBuffer[obp++]=(char)0xDD; OpBuffer[obp++]=(char)0x00; } else if(type==DEF_SINGLE||type==DEF_DWORD){ //pop eax op_pop(REG_EAX); //mov eax,dword ptr[eax] OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x00; } else if(type==DEF_QWORD){ //pop ecx op_pop(REG_ECX); //mov eax,dword ptr[ecx] op_mov_RM(sizeof(long),REG_EAX,REG_ECX,0,MOD_BASE); //mov edx,dword ptr[ecx+sizeof(long)] op_mov_RM(sizeof(long),REG_EDX,REG_ECX,sizeof(long),MOD_BASE_DISP8); } else if(type==DEF_WORD){ //pop ebx op_pop(REG_EBX); //xor eax,eax OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xC0; //mov ax,word ptr[ebx] OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x03; } else if(type==DEF_BYTE){ //pop ebx op_pop(REG_EBX); //xor eax,eax OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xC0; //mov al,byte ptr[ebx] OpBuffer[obp++]=(char)0x8A; OpBuffer[obp++]=(char)0x03; } } bool Opcode_CallFunc( const char *Parameter, const int FuncNum, 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: 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_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; }