#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(); Variables &vars = UserProc::IsGlobalAreaCompiling()? globalVars : UserProc::CompilingUserProc().localVars; //使用済みローカル変数の生存チェックを外す foreach( Variable *pVar, vars ){ if(pVar->bLiving&&pVar->ScopeLevel==level){ pVar->bLiving=0; extern int obp; pVar->ScopeEndAddress=obp; } } //スコープ抜け出しスケジュール ppScopes[level]->RunScheduleOfBreak(); //スコープレベルを下げる 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(){ Variables &vars = UserProc::IsGlobalAreaCompiling()? globalVars : UserProc::CompilingUserProc().localVars; int i3; int indexSystemGC=-1; for( i3 = (int)vars.size() - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする Variable *pVar = vars[i3]; if( UserProc::IsGlobalAreaCompiling() && GetNowLevel() == 0 ){ if( pVar->GetName() == "_System_GC" ){ indexSystemGC=i3; continue; } } //同一レベルのレキシカルスコープのみを検知 if(!pVar->bLiving) continue; if( pVar->ScopeLevel != GetNowLevel() ) continue; if( pVar->IsStruct() && pVar->IsParameter() ){ //構造体パラメータを持つとき //メモリを解放する #ifdef _AMD64_ //x64ビットコード //mov rcx,qword ptr[rsp+offset] op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, -pVar->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->offset,MOD_BASE_DISP32); obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); //push ecx op_push(REG_ECX); #endif //call free extern UserProc *pSub_free; op_call(pSub_free); if( UserProc::IsGlobalAreaCompiling() ){ //ここには来ないハズ SetError(300,NULL,cp); } } } if(indexSystemGC!=-1){ //_System_GCオブジェクトのデストラクタの呼び出し処理 const CMethod *method = vars[indexSystemGC]->GetClass().GetDestructorMethod(); if( method ){ Opcode_CallProc("",method->pUserProc,0,vars[indexSystemGC]->GetName().c_str(),DEF_OBJECT); } } } // Returnステートメントで発行されるデストラクタを生成 void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ //現在のスコープレベルを退避 int backupScopeLevel = GetNowLevel(); for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ SetNowLevel( i ); CallDestructorsOfScopeEnd(); } //現在のスコープレベルを復元 SetNowLevel( backupScopeLevel ); }