#include "../BasicCompiler_Common/common.h" #include "Opcode.h" int GetFunctionType(int FuncNum){ switch(FuncNum){ case FUNC_LEN: return DEF_LONG; case FUNC_SIZEOF: return DEF_LONG; case FUNC_ADDRESSOF: case FUNC_VARPTR: return DEF_PTR_VOID; 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,"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_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(),NULL); 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 rax,TypeSize op_mov_RV(sizeof(_int64),REG_RAX,typeSize); return; } 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; } //オーバーロードを解決 extern ProcPointer **ppProcPointer; pUserProc=OverloadSolution(name,subs,ppProcPointer[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; SetVarPtrToReg(REG_RCX,&RelativeVar); //参照タイプが整合しているかをチェック if(type.GetBasicType()!=RefType) SetError(104,ObjectName,cp); if(type.IsObjectPtr()){ //mov rcx,qword ptr[rcx] op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE); } } } else{ InClassMember: //自身のオブジェクトのThisポインタをrcxにコピー SetThisPtrToReg(REG_RCX); pobj_c=pobj_CompilingClass; } //仮想関数(オブジェクトメソッド) //pObj->func_table->func1 // ->func2 // ->func3 //mov r11,qword ptr[rcx] 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){ op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,i2*PTR_SIZE,MOD_BASE_DISP8); } else{ op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,i2*PTR_SIZE,MOD_BASE_DISP32); } } else{ //一般の関数 //mov rax,ProcAddr op_mov_RV(sizeof(_int64),REG_RAX,0); obp-=sizeof(long); 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 rax,size op_mov_RV(sizeof(_int64),REG_RAX,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(); SetVarPtrToReg(REG_RAX,&RelativeVar); if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){ //参照をオブジェクトポインタに変更 //mov rax,qword ptr[rax] op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE ); } } 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] op_movlpd_RM(REG_XMM0,REG_RAX,0,MOD_BASE); } else if(type==DEF_SINGLE){ //movss xmm0,dword ptr[rax] op_movss_RM(REG_XMM0,REG_RAX,0,MOD_BASE); } else{ //mov rax,ptr[rax] op_mov_RM(GetTypeSize(type,-1),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_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; }