#include "stdafx.h" #include #include #include "../common.h" #ifdef _AMD64_ #include "../../BasicCompiler64/opcode.h" #else #include "../../BasicCompiler32/opcode.h" #endif void LexicalScope::Break(){ //未解放のローカルオブジェクトを解放する compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn( level ); //jmp ...(Next addr) breakPertialSchedules.push_back( compiler.codeGenerator.op_jmp( 0, sizeof(long), true ) ); } void LexicalScope::RunScheduleOfBreak(){ BOOST_FOREACH( const PertialSchedule *pBreakPertialSchedule, breakPertialSchedules ) { compiler.codeGenerator.opfix_JmpPertialSchedule( pBreakPertialSchedule ); } } LexicalScope *LexicalScopes::SearchScope( LexicalScope::SCOPE_TYPE TypeOfStatement ){ for( int i = level; i>=0; i-- ){ if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){ return ppScopes[i]; } } return NULL; } void LexicalScopes::Init(int addr){ // TODO: エラーチェック level = -1; Start( addr, LexicalScope::SCOPE_TYPE_BASE ); } void LexicalScopes::Start( int addr, LexicalScope::SCOPE_TYPE TypeOfStatement ){ level++; ppScopes = (LexicalScope **)realloc( ppScopes, ( level + 1 ) * sizeof( LexicalScope * ) ); ppScopes[level] = new LexicalScope( level, addr, TypeOfStatement ); } int LexicalScopes::GetNowLevel(){ return level; } void LexicalScopes::SetNowLevel( int level ){ this->level = level; } int LexicalScopes::GetStartAddress(){ return ppScopes[level]->GetStartAddress(); } void LexicalScopes::End(){ if( level <= 0 ){ SetError(); return; } //デストラクタを呼ぶ CallDestructorsOfScopeEnd(); Variables &vars = UserProc::IsGlobalAreaCompiling() ? compiler.GetMeta().GetGlobalVars() : UserProc::CompilingUserProc().GetLocalVars(); //使用済みローカル変数の生存チェックを外す BOOST_FOREACH( Variable *pVar, vars ){ if(pVar->bLiving&&pVar->GetScopeLevel()==level){ pVar->bLiving=0; extern int obp; pVar->SetScopeEndAddress( obp ); } } //スコープ抜け出しスケジュール ppScopes[level]->RunScheduleOfBreak(); //スコープレベルを下げる delete ppScopes[level]; level--; } // スコープ終了時のデストラクタ呼び出し void LexicalScopes::CallDestructorsOfScopeEnd(){ Variables &vars = UserProc::IsGlobalAreaCompiling() ? compiler.GetMeta().GetGlobalVars() : UserProc::CompilingUserProc().GetLocalVars(); 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->GetScopeLevel() != GetNowLevel() ) continue; if( pVar->GetType().IsStruct() && pVar->IsParameter() ){ //構造体パラメータを持つとき //メモリを解放する #ifdef _AMD64_ //x64ビットコード //mov rcx,qword ptr[rsp+offset] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, -pVar->GetOffsetAddress(), MOD_BASE_DISP32, Schedule::LocalVar); #else //x86コード //mov ecx,dword ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->GetOffsetAddress(),MOD_BASE_DISP32, Schedule::None, true ) ); //push ecx compiler.codeGenerator.op_push(REG_ECX); #endif //call free extern const UserProc *pSub_free; compiler.codeGenerator.op_call(pSub_free); if( UserProc::IsGlobalAreaCompiling() ){ //ここには来ないハズ SetError(300,NULL,cp); } } } if(indexSystemGC!=-1){ //_System_GCオブジェクトのデストラクタの呼び出し処理 const CMethod *method = vars[indexSystemGC]->GetType().GetClass().GetDestructorMethod(); if( method ){ Opcode_CallProc("",&method->GetUserProc(),0,vars[indexSystemGC]->GetName().c_str(),DEF_OBJECT); } } } // Returnステートメントで発行されるデストラクタを生成 void LexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ //現在のスコープレベルを退避 int backupScopeLevel = GetNowLevel(); for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ SetNowLevel( i ); CallDestructorsOfScopeEnd(); } //現在のスコープレベルを復元 SetNowLevel( backupScopeLevel ); }