#include "stdafx.h" #include #include #include #include #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" void SystemProc( const UserProc &userProc ){ if( userProc.GetName() == "_System_GetEip" ){ //mov rax,qword ptr[rsp] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_RSP,0,MOD_BASE); //ret compiler.codeGenerator.op_ret(); } else if( userProc.GetName() == "_System_InitDllGlobalVariables" ){ //////////////////////////////////////// // DLLのグローバル領域をコンパイル //////////////////////////////////////// if(!compiler.IsDll()){ //ret compiler.codeGenerator.op_ret(); return; } const UserProc *pBackUserProc = &UserProc::CompilingUserProc(); UserProc::CompileStartForGlobalArea(); int BackCp; BackCp=cp; cp=-1; //sub rsp,スタックフレームサイズ const PertialSchedule *pStackFramePertialSchedule = compiler.codeGenerator.op_sub_rsp( 0, true ); extern BOOL bDebugCompile; if(bDebugCompile){ //デバッグ用の変数を定義 DebugVariable(); } //GC用の変数を定義 InitGCVariables(); //_System_StartupProgramの呼び出し extern const UserProc *pSub_System_StartupProgram; compiler.codeGenerator.op_call(pSub_System_StartupProgram); //クラスに属する静的メンバを定義 compiler.GetObjectModule().meta.GetClasses().InitStaticMember(); GetGlobalDataForDll(); //add rsp,スタックフレームサイズ compiler.codeGenerator.op_add_RV(REG_RSP,pobj_sf->GetFrameSize(0)); //スタックフレームスケジュール(subコマンドに渡す値) compiler.codeGenerator.opfix( pStackFramePertialSchedule, pobj_sf->GetFrameSize(0) ); UserProc::CompileStartForUserProc( pBackUserProc ); cp=BackCp; //ret compiler.codeGenerator.op_ret(); } else if( userProc.GetName() == "_System_InitStaticLocalVariables" ){ //静的ローカルオブジェクトのコンストラクタ呼び出し //sub rsp,スタックフレームサイズ const PertialSchedule *pStackFramePertialSchedule = compiler.codeGenerator.op_sub_rsp( 0, true ); BOOST_FOREACH( Variable *pVar, compiler.GetObjectModule().meta.GetGlobalVars() ){ if(memicmp(pVar->GetName().c_str(),"Static%",7)==0){ //コンストラクタ呼び出し if( pVar->GetType().IsObject() ){ //エラー用 cp=pVar->source_code_address; CallConstructor( pVar->GetName().c_str(), pVar->GetSubscripts(), pVar->GetType(), pVar->GetParamStrForConstructor().c_str()); } } } //add rsp,スタックフレームサイズ compiler.codeGenerator.op_add_RV(REG_RSP,pobj_sf->GetFrameSize(0)); //スタックフレームスケジュール(subコマンドに渡す値) compiler.codeGenerator.opfix( pStackFramePertialSchedule, pobj_sf->GetFrameSize(0) ); //ret compiler.codeGenerator.op_ret(); } else if( userProc.GetName() == "_System_Call_Destructor_of_GlobalObject" ){ //sub rsp,8(※RSPを16バイト境界にあわせるため) compiler.codeGenerator.op_sub_rsp(0x8); const UserProc *pBackUserProc = &UserProc::CompilingUserProc(); UserProc::CompileStartForGlobalArea(); compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd(); UserProc::CompileStartForUserProc( pBackUserProc ); //add rsp,8 compiler.codeGenerator.op_add_RV(REG_RSP,0x8); //ret compiler.codeGenerator.op_ret(); } else if( userProc.GetName() == "_System_GetSp" ){ //mov rax,rsp compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RSP); //add rax,PTR_SIZE compiler.codeGenerator.op_add_RV(REG_RAX,PTR_SIZE); //ret compiler.codeGenerator.op_ret(); } else{ SetError(); } } void AutoGeneration(const UserProc &userProc){ if( userProc.GetName() == "InitializeUserTypes" && userProc.HasParentClass() && userProc.GetParentClass().GetName() == "_System_TypeBase" ){ compiler.GetObjectModule().meta.GetClasses().Compile_System_InitializeUserTypes(); } else if( userProc.GetName() == "RegisterGlobalRoots" && userProc.HasParentClass() && userProc.GetParentClass().GetName() == "_System_CGarbageCollection" ){ Compile_AddGlobalRootsForGc(); } else if( userProc.GetName() == compiler.globalAreaProcName ){ //////////////////////////////////////// // グローバル領域をコンパイル //////////////////////////////////////// const UserProc *pBackUserProc = &UserProc::CompilingUserProc(); UserProc::CompileStartForGlobalArea(); int BackCp = cp; cp=-1; //クラスに属する静的メンバを定義 compiler.GetObjectModule().meta.GetClasses().InitStaticMember(); //グローバル実行領域をコンパイル開始 CompileBuffer(0,0); //Goto未知ラベルスケジュールが存在したらエラーにする BOOST_FOREACH( const GotoLabelSchedule *pGotoLabelSchedule, compiler.codeGenerator.gotoLabelSchedules ) { if(pGotoLabelSchedule->GetName().size()>0){ SetError(6,pGotoLabelSchedule->GetName(),pGotoLabelSchedule->GetSourceCodePos()); } else{ char temporary[255]; sprintf(temporary,"%d",pGotoLabelSchedule->GetLineNum()); SetError(6,temporary,pGotoLabelSchedule->GetSourceCodePos()); } } UserProc::CompileStartForUserProc( pBackUserProc ); cp=BackCp; } else{ SetError(); } } void _compile_proc(const UserProc *pUserProc){ extern char *basbuf; extern HANDLE hHeap; extern BOOL bDebugCompile; int i3,i4; char temporary[VN_SIZE]; if( pUserProc->GetLocalVars().size() ){ SetError(); return; } trace_for_sourcecodestep( "★★★ " << pUserProc->GetFullName() << "のコンパイルを開始" ); pUserProc->CompleteCompile(); extern BOOL bSystemProc; if(memcmp(pUserProc->GetName().c_str(),"_System_",8)==0) bSystemProc=1; else bSystemProc=0; extern BOOL bDebugSupportProc; if(memcmp(pUserProc->GetName().c_str(),"_DebugSys_",10)==0){ if(!bDebugCompile){ return; } bDebugSupportProc=1; } else bDebugSupportProc=0; //コンパイル中の関数が属するクラス compiler.pCompilingClass=pUserProc->GetParentClassPtr(); //コンパイルスタートをクラス管理クラスに追加 compiler.GetObjectModule().meta.GetClasses().StartCompile( pUserProc ); //コンパイル中の関数 UserProc::CompileStartForUserProc( pUserProc ); // コンパイル中の関数が属する名前空間 compiler.GetNamespaceSupporter().SetLivingNamespaceScopes( pUserProc->GetNamespaceScopes() ); // コンパイル中の関数でImportsされている名前空間 compiler.GetNamespaceSupporter().SetImportedNamespaces( pUserProc->GetImportedNamespaces() ); // コード生成対象を選択 compiler.codeGenerator.Select( (const_cast(pUserProc))->GetNativeCode() ); if(pUserProc->IsSystem()){ //////////////////// // 特殊関数 //////////////////// extern int AllLocalVarSize; AllLocalVarSize=0; //スタックフレーム管理用オブジェクトを初期化 extern StackFrame *pobj_sf; pobj_sf=new StackFrame(); SystemProc(*pUserProc); //スタックフレーム管理用オブジェクトを破棄 delete pobj_sf; pobj_sf=0; return; } cp=pUserProc->GetCodePos(); for(;;cp++){ if(IsCommandDelimitation(basbuf[cp])) break; } cp--; //プロシージャ抜け出しスケジュール(Exit Sub/Function) compiler.codeGenerator.exitSubCodePositions.clear(); //ラベル用のメモリを確保 compiler.codeGenerator.gotoLabels.clear(); //Gotoラベルスケジュール compiler.codeGenerator.gotoLabelSchedules.clear(); //With情報のメモリを確保 extern WITHINFO WithInfo; WithInfo.ppName=(char **)HeapAlloc(hHeap,0,1); WithInfo.pWithCp=(int *)HeapAlloc(hHeap,0,1); WithInfo.num=0; //重複エラー情報管理のメモリを確保 extern char **SynonymErrorWords; extern int SynonymErrorNum; SynonymErrorNum=0; SynonymErrorWords=(char **)HeapAlloc(hHeap,0,1); //Continueアドレスを初期化 compiler.codeGenerator.ClearContinueArea(); //ローカル変数に関する情報 extern int AllLocalVarSize; AllLocalVarSize=0; //レキシカルスコープ情報を初期化 compiler.codeGenerator.lexicalScopes.Init( compiler.codeGenerator.GetNativeCodeSize() ); ///////////////////////////////////// // パラメータ用の変数データを考慮 ///////////////////////////////////// //パラメータ用の変数データを考慮 for(i3=(int)pUserProc->RealParams().size()-1;i3>=0;i3--){ Parameter ¶m = *pUserProc->RealParams()[i3]; Variable *pVar = new Variable( param.GetVarName(), param, false, param.IsRef(), "", false ); if( param.IsArray() ){ pVar->SetArray( param.GetSubscripts() ); } int varSize; if( param.IsRef() == false && param.IsStruct() ){ //構造体のByValパラメータ pVar->ThisIsParameter(); varSize=PTR_SIZE; } else{ if( param.IsArray() == false ){ varSize = pVar->GetMemorySize(); } else{ varSize=PTR_SIZE; } } AllLocalVarSize+=varSize; pVar->SetOffsetAddress( AllLocalVarSize ); //レキシカルスコープ情報 pVar->SetScopeLevel( compiler.codeGenerator.lexicalScopes.GetNowLevel() ); pVar->SetScopeStartAddress( compiler.codeGenerator.lexicalScopes.GetStartAddress() ); pVar->bLiving=TRUE; pUserProc->GetLocalVars().push_back( pVar ); } //Thisポインタを示すローカルオフセット値をセット extern int LocalVar_ThisPtrOffset; LocalVar_ThisPtrOffset=AllLocalVarSize; //スタックフレーム管理用クラスを初期化 extern StackFrame *pobj_sf; pobj_sf=new StackFrame(); /////////////////////// // ここからコード生成 for(i3=(int)pUserProc->RealParams().size()-1;i3>=0;i3--){ Parameter ¶m = *pUserProc->RealParams()[i3]; if(i3==3){ if(param.IsReal()&¶m.IsRef() == false){ //movsd qword ptr[rsp+0x20],xmm3 compiler.codeGenerator.op_movsd_MR(REG_XMM3,REG_RSP,0x20,MOD_BASE_DISP32); } else{ //mov qword ptr[rsp+0x20],r9 compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_R9,REG_RSP,0x20,MOD_BASE_DISP32); } } if(i3==2){ if(param.IsReal()&¶m.IsRef() == false){ //movsd qword ptr[rsp+0x18],xmm2 compiler.codeGenerator.op_movsd_MR(REG_XMM2,REG_RSP,0x18,MOD_BASE_DISP32); } else{ //mov qword ptr[rsp+0x18],r8 compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_R8,REG_RSP,0x18,MOD_BASE_DISP32); } } if(i3==1){ if(param.IsReal()&¶m.IsRef() == false){ //movsd qword ptr[rsp+0x10],xmm1 compiler.codeGenerator.op_movsd_MR(REG_XMM1,REG_RSP,0x10,MOD_BASE_DISP32); } else{ //mov qword ptr[rsp+0x10],rdx compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RDX,REG_RSP,0x10,MOD_BASE_DISP32); } } if(i3==0){ if(param.IsReal()&¶m.IsRef() == false){ //movsd qword ptr[rsp+0x8],xmm0 compiler.codeGenerator.op_movsd_MR(REG_XMM0,REG_RSP,0x8,MOD_BASE_DISP32); } else{ //mov qword ptr[rsp+0x8],rcx compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RCX,REG_RSP,0x8,MOD_BASE_DISP32); } } } //ret用のアドレスを考慮 AllLocalVarSize+=sizeof(_int64); //sub rsp,スタックフレームサイズ const PertialSchedule *pStackFramePertialSchedule = compiler.codeGenerator.op_sub_rsp( 0, true ); //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 pobj_sf->push(REG_RBX); pobj_sf->push(REG_RSI); pobj_sf->push(REG_RDI); pobj_sf->push(REG_R12); pobj_sf->push(REG_R13); pobj_sf->push(REG_R14); pobj_sf->push(REG_R15); //ローカル変数のベース値 int BaseLocalVar; BaseLocalVar=AllLocalVarSize; if( !pUserProc->ReturnType().IsNull() ){ //戻り値が存在するとき const char *temp = pUserProc->GetName().c_str(); if( temp[0]==1&&temp[1]==ESC_OPERATOR ){ temp = "_System_ReturnValue"; } if( pUserProc->ReturnType().IsStruct() ){ //戻り値用の構造体(値型)はパラメータで引き渡される } else{ if( pUserProc->ReturnType().IsObject() ){ sprintf(temporary,"%s=Nothing%c%c%s",temp,1,ESC_AS, compiler.TypeToString( pUserProc->ReturnType() ).c_str() ); } else{ //戻り値用の変数の定義 sprintf(temporary,"%s%c%c%s",temp,1,ESC_AS, compiler.TypeToString( pUserProc->ReturnType() ).c_str() ); } OpcodeDim(temporary,0); } } const PertialSchedule *pRspOffsetPertialSchedule1 = NULL; const PertialSchedule *pRspOffsetPertialSchedule2 = NULL; if(bDebugCompile&&bDebugSupportProc==0){ //mov rdx, qword ptr[rsp+スタックフレームサイズ] pRspOffsetPertialSchedule1 = compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RDX,REG_RSP,0,MOD_BASE_DISP32, Schedule::None, true ); //mov rcx,rsp compiler.codeGenerator.op_mov_RR(REG_RCX,REG_RSP); //add rcx,スタックフレームサイズ+sizeof(_int64) ※ret用のサイズを考慮 pRspOffsetPertialSchedule2 = compiler.codeGenerator.op_add_RV(REG_RCX,0, Schedule::None, true ); //call _DebugSys_StartProc extern const UserProc *pSub_DebugSys_StartProc; compiler.codeGenerator.op_call(pSub_DebugSys_StartProc); } if(compiler.pCompilingClass){ if( pUserProc->GetName() == compiler.pCompilingClass->GetName() ){ //////////////////////////////////// // コンストラクタをコンパイルするとき //////////////////////////////////// //コンストラクタのコンパイル開始を通知 compiler.pCompilingClass->NotifyStartConstructorCompile(); //基底クラスかどうかの識別 //(継承元がインターフェイスの場合も基底クラスと見なす) BOOL bThisIsSuperClass; if( !compiler.pCompilingClass->HasSuperClass() ) bThisIsSuperClass=1; else if( compiler.pCompilingClass->GetSuperClass().GetConstructorMethod() == NULL ){ //インターフェイスを継承したときはコンストラクタを持たない bThisIsSuperClass=1; } else bThisIsSuperClass=0; if(!bThisIsSuperClass){ /* サブクラスコンストラクタをコンパイルしているときは、 基底クラスのコンストラクタを呼び出す */ i3=cp+1; while(IsCommandDelimitation(basbuf[i3])) i3++; for(i4=0;;i3++,i4++){ if(!IsVariableChar(basbuf[i3])){ temporary[i4]=0; break; } temporary[i4]=basbuf[i3]; } if( compiler.pCompilingClass->GetSuperClass().GetName() == temporary ){ //基底クラスのコンストラクタを呼び出す cp=i3; for(i4=0;;cp++,i4++){ if(IsCommandDelimitation(basbuf[cp])){ temporary[i4]=0; break; } temporary[i4]=basbuf[cp]; } if(!(temporary[0]=='('&&temporary[lstrlen(temporary)-1]==')')){ SetError(1,NULL,cp); } RemoveStringPare(temporary); Type dummyType; CallProc( PROC_DEFAULT , &compiler.pCompilingClass->GetSuperClass().GetConstructorMethod()->GetUserProc() , compiler.pCompilingClass->GetSuperClass().GetConstructorMethod()->GetUserProc().GetName().c_str() , temporary , dummyType ); } else{ //基底クラスのコンストラクタを暗黙的に呼び出す Opcode_CallProc("", &compiler.pCompilingClass->GetSuperClass().GetConstructorMethod()->GetUserProc(), 0, ""); } } //仮想関数テーブルを初期化 if( compiler.pCompilingClass->IsExistVirtualFunctions() && !compiler.pCompilingClass->IsAbstract() ) { // mov rax,vtblAddress compiler.codeGenerator.op_mov_RV_vtbl( REG_RAX, compiler.pCompilingClass ); //Thisポインタをrcxにコピー SetThisPtrToReg(REG_RCX); //mov qword ptr[rcx],rax compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,REG_RCX,0,MOD_BASE); // 仮想関数になるメソッドに使用チェックをつける BOOST_FOREACH( const CMethod *pMethod, compiler.pCompilingClass->GetMethods() ) { if( pMethod->IsVirtual() ) { pMethod->GetUserProc().Using(); } } } } else if( pUserProc->IsDestructor() ){ //デストラクタをコンパイルしたとき //デストラクタのコンパイル開始を通知 compiler.pCompilingClass->NotifyStartDestructorCompile(); } } ////////////////////////////////////////// ////////////////////////////////////////// ////// プロシージャ内をコンパイル //////// if( pUserProc->IsAutoGeneration() ){ AutoGeneration( *pUserProc ); } else{ if(pUserProc->IsMacro()){ CompileBuffer(ESC_ENDMACRO,0); } else{ if(pUserProc->IsSub()){ CompileBuffer(ESC_ENDSUB,0); } else if(pUserProc->IsFunction()){ CompileBuffer(ESC_ENDFUNCTION,0); } } } ////////////////////////////////////////// ////////////////////////////////////////// if( compiler.pCompilingClass ){ if( compiler.pCompilingClass->IsCompilingConstructor() ){ // コンストラクタをコンパイルしていたとき // コンストラクタのコンパイルが完了したことを通知 compiler.pCompilingClass->NotifyFinishConstructorCompile(); } else if( pUserProc->IsDestructor() ){ //////////////////////////////////// //デストラクタをコンパイルしたとき //////////////////////////////////// // デストラクタのコンパイルが完了したことを通知 compiler.pCompilingClass->NotifyFinishDestructorCompile(); if( compiler.pCompilingClass->HasSuperClass() ){ /* サブクラスのデストラクタをコンパイルしているときは、 基底クラスのデストラクタを呼び出す */ const CMethod *method = compiler.pCompilingClass->GetSuperClass().GetDestructorMethod(); if( method ){ Opcode_CallProc("", &method->GetUserProc(), 0, ""); } } } } //With情報のメモリを解放 for(i3=0;i3ReturnType().IsNull() ){ ////////////////////////////////// // 戻り値をraxまたはxmm0に設定 ////////////////////////////////// RELATIVE_VAR RelativeVar; const char *temp = pUserProc->GetName().c_str(); if( temp[0]==1 && temp[1]==ESC_OPERATOR ){ temp="_System_ReturnValue"; } GetVarOffsetReadWrite(temp,&RelativeVar,Type()); const Type &returnType = pUserProc->ReturnType(); if( returnType.IsObject() || returnType.IsStruct() ) { SetVarPtrToReg(REG_RAX,&RelativeVar); if( returnType.IsObject() ) { //mov rax,qword ptr[rax] compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE ); } } else if( returnType.IsDouble() ) { //64ビット実数型 SetXmmReg_DoubleVariable(&RelativeVar,REG_XMM0); } else if( returnType.IsSingle() ) { //32ビット実数型 SetXmmReg_SingleVariable(&RelativeVar,REG_XMM0); } else if( returnType.IsWhole() ) { //整数型 SetReg_WholeVariable(returnType,&RelativeVar,REG_RAX); } else SetError(300,NULL,cp); } //ローカル変数領域のサイズをスタックフレームに通知 int localParmSize = AllLocalVarSize - BaseLocalVar; int stackFrameSize = pobj_sf->GetFrameSize( localParmSize ); //ローカル変数アドレススケジュール BOOST_FOREACH( const PertialSchedule *pPertialSchedule, compiler.codeGenerator.localVarPertialSchedules ) { compiler.codeGenerator.opfix_offset( pPertialSchedule, AllLocalVarSize + stackFrameSize ); } compiler.codeGenerator.localVarPertialSchedules.clear(); BOOST_FOREACH( Variable *pVar, pUserProc->GetLocalVars() ){ //後にデバッグで利用する pVar->SetOffsetAddress( AllLocalVarSize + stackFrameSize - pVar->GetOffsetAddress() ); } //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R15); pobj_sf->pop(REG_R14); pobj_sf->pop(REG_R13); pobj_sf->pop(REG_R12); pobj_sf->pop(REG_RDI); pobj_sf->pop(REG_RSI); pobj_sf->pop(REG_RBX); int stackFrameAndLocalParamSize = localParmSize + stackFrameSize; //add rsp,スタックフレームサイズ compiler.codeGenerator.op_add_rsp(stackFrameAndLocalParamSize); //ret compiler.codeGenerator.op_ret(); //デバッグ用 if( pRspOffsetPertialSchedule1 ){ compiler.codeGenerator.opfix( pRspOffsetPertialSchedule1, stackFrameAndLocalParamSize ); compiler.codeGenerator.opfix( pRspOffsetPertialSchedule2, stackFrameAndLocalParamSize + sizeof(_int64) ); } //スタックフレームスケジュール(subコマンド) compiler.codeGenerator.opfix( pStackFramePertialSchedule, stackFrameAndLocalParamSize ); //スタックフレームスケジュールを実行 pobj_sf->RunningSchedule( stackFrameSize ); delete pobj_sf; pobj_sf=0; //重複エラー情報管理のメモリを解放 for(i3=0;i3