#include "common.h" #ifdef _AMD64_ #include "../BasicCompiler64/opcode.h" #else #include "../BasicCompiler32/opcode.h" #endif CLexicalScopes obj_LexScopes; CScope::CScope( int level, int addr, SCOPE_TYPE TypeOfStatement ){ this->level = level; this->StartAddress = addr; this->TypeOfStatement = TypeOfStatement; pBreakSchedule = (DWORD *)malloc( 1 ); nBreakSchedule = 0; } CScope::~CScope(){ free( pBreakSchedule ); } int CScope::GetStartAddress(){ return StartAddress; } SCOPE_TYPE CScope::GetTypeOfStatement(){ return TypeOfStatement; } void CScope::Break(){ //未解放のローカルオブジェクトを解放する obj_LexScopes.CallDestructorsOfReturn( level ); //jmp ...(Next addr) OpBuffer[obp++]=(char)0xE9; pBreakSchedule=(DWORD *)realloc( pBreakSchedule, ( nBreakSchedule + 1 ) * sizeof(DWORD) ); pBreakSchedule[nBreakSchedule]=obp; nBreakSchedule++; obp+=sizeof(long); } void CScope::RunScheduleOfBreak(){ for(int i=0;i=0; i-- ){ if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){ return ppScopes[i]; } } return NULL; } CLexicalScopes::CLexicalScopes(){ ppScopes = (CScope **)malloc( 1 ); level=0; } CLexicalScopes::~CLexicalScopes(){ free( ppScopes ); } void CLexicalScopes::Init(int addr){ // TODO: エラーチェック level = -1; Start( addr, SCOPE_TYPE_BASE ); } void CLexicalScopes::Start( int addr, SCOPE_TYPE TypeOfStatement ){ level++; ppScopes = (CScope **)realloc( ppScopes, ( level + 1 ) * sizeof( CScope * ) ); ppScopes[level] = new CScope( level, addr, TypeOfStatement ); } void CLexicalScopes::End(){ if( level <= 0 ){ SetError(300,NULL,cp); return; } //デストラクタを呼ぶ CallDestructorsOfScopeEnd(); extern BOOL bCompilingGlobal; VARIABLE *pVar; int num; if(bCompilingGlobal){ //グローバル領域をコンパイルしているとき extern VARIABLE *GlobalVar; extern int MaxGlobalVarNum; pVar=GlobalVar; num=MaxGlobalVarNum; } else{ //ローカル領域をコンパイルしているとき extern VARIABLE *LocalVar; extern int MaxLocalVarNum; pVar=LocalVar; num=MaxLocalVarNum; } //使用済みローカル変数の生存チェックを外す for(int i=0;iRunScheduleOfBreak(); //スコープレベルを下げる delete ppScopes[level]; level--; } void CLexicalScopes::ExitFor(){ CScope *pScope = SearchScope( SCOPE_TYPE_FOR ); if( !pScope ){ SetError(12,"Exit For",cp); return; } pScope->Break(); } void CLexicalScopes::ExitWhile(){ CScope *pScope = SearchScope( SCOPE_TYPE_WHILE ); if( !pScope ){ SetError(12,"Exit While",cp); return; } pScope->Break(); } void CLexicalScopes::ExitDo(){ CScope *pScope = SearchScope( SCOPE_TYPE_DO ); if( !pScope ){ SetError(12,"Exit Do",cp); return; } pScope->Break(); } int CLexicalScopes::GetNowLevel(){ return level; } void CLexicalScopes::SetNowLevel( int level ){ this->level = level; } int CLexicalScopes::GetStartAddress(){ return ppScopes[level]->GetStartAddress(); } // スコープ終了時のデストラクタ呼び出し void CLexicalScopes::CallDestructorsOfScopeEnd(){ extern BOOL bCompilingGlobal; VARIABLE *pVar; int num; if(bCompilingGlobal){ //グローバルオブジェクトの解放処理 extern VARIABLE *GlobalVar; extern int MaxGlobalVarNum; pVar=GlobalVar; num=MaxGlobalVarNum; } else{ //ローカルオブジェクトの解放処理 extern VARIABLE *LocalVar; extern int MaxLocalVarNum; pVar=LocalVar; num=MaxLocalVarNum; } int i3; int indexSystemGC=-1; for( i3 = num - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする if( bCompilingGlobal && GetNowLevel() == 0 ){ if(lstrcmp(pVar[i3].name,"_System_GC")==0){ indexSystemGC=i3; continue; } } //同一レベルのレキシカルスコープのみを検知 if(!pVar[i3].bLiving) continue; if( pVar[i3].ScopeLevel != GetNowLevel() ) continue; if(pVar[i3].type==DEF_STRUCT&&pVar[i3].fRef&OBJECT_PARAMETER){ //構造体パラメータを持つとき //メモリを解放する #ifdef _AMD64_ //x64ビットコード //mov rcx,qword ptr[rsp+offset] op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, -pVar[i3].offset, MOD_BASE_DISP32); obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); #else //x86コード //mov ecx,dword ptr[ebp+offset] op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32); obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); //push ecx op_push(REG_ECX); #endif //call free extern SUBINFO *pSub_free; op_call(pSub_free); if(bCompilingGlobal){ //ここには来ないハズ SetError(300,NULL,cp); } } /* TODO: 消す else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){ //デストラクタの呼び出し CMethod *method = pVar[i3].u.pobj_c->GetDestructorMethod(); if( method ){ int ss[MAX_ARRAYDIM]; memset(ss,0,MAX_ARRAYDIM*sizeof(int)); if(pVar[i3].SubScripts[0]!=-1){ while(1){ for(i4=0;;i4++){ if(pVar[i3].SubScripts[i4]==-1) break; if(ss[i4]>pVar[i3].SubScripts[i4]){ ss[i4]=0; ss[i4+1]++; } else break; } if(pVar[i3].SubScripts[i4]==-1) break; char temporary[VN_SIZE]; sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]); for(i4=1;;i4++){ if(pVar[i3].SubScripts[i4]==-1) break; sprintf(temporary+lstrlen(temporary),",%d",ss[i4]); } lstrcat(temporary,"]"); Opcode_CallProc("",method->psi,0,temporary,DEF_OBJECT); ss[0]++; //ネイティブコードバッファの再確保 extern int obp_AllocSize; if(obp_AllocSizepsi,0,pVar[i3].name,DEF_OBJECT); } } } */ } if(indexSystemGC!=-1){ //_System_GCオブジェクトのデストラクタの呼び出し処理 CMethod *method = pVar[indexSystemGC].u.pobj_c->GetDestructorMethod(); if( method ){ Opcode_CallProc("",method->psi,0,pVar[indexSystemGC].name,DEF_OBJECT); } } } // Returnステートメントで発行されるデストラクタを生成 void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ //現在のスコープレベルを退避 int backupScopeLevel = GetNowLevel(); for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ SetNowLevel( i ); CallDestructorsOfScopeEnd(); } //現在のスコープレベルを復元 SetNowLevel( backupScopeLevel ); }