#include "stdafx.h" #include #include #include "../common.h" #ifdef _AMD64_ #include "../../compiler_x64/opcode.h" #else #include "../../compiler_x86/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(){ 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 ){ compiler.errorMessenger.OutputFatalError(); return; } //デストラクタを呼ぶ CallDestructorsOfScopeEnd(); Variables *pVars = compiler.IsGlobalAreaCompiling() ? &compiler.GetObjectModule().meta.GetGlobalVars() : &compiler.GetCompilingUserProc().GetLocalVars(); //使用済みローカル変数の生存チェックを外す foreach( Variable *pVar, (*pVars) ) { if( pVar->isLiving && pVar->GetScopeLevel() == level ) { pVar->isLiving = false; pVar->SetScopeEndAddress( compiler.codeGenerator.GetNativeCodeSize() ); } } //スコープ抜け出しスケジュール ppScopes[level]->RunScheduleOfBreak(); //スコープレベルを下げる delete ppScopes[level]; level--; } // スコープ終了時のデストラクタ呼び出し void LexicalScopes::CallDestructorsOfScopeEnd(){ Variables *pVariabls = compiler.IsGlobalAreaCompiling() ? &compiler.GetObjectModule().meta.GetGlobalVars() : &compiler.GetCompilingUserProc().GetLocalVars(); int i3; int indexSystemGC=-1; for( i3 = (int)pVariabls->size() - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする Variable *pVar = (*pVariabls)[i3]; if( compiler.IsGlobalAreaCompiling() && GetNowLevel() == 0 ){ if( pVar->GetName() == "_System_GC" ){ indexSystemGC=i3; continue; } } //同一レベルのレキシカルスコープのみを検知 if( !pVar->isLiving ) continue; if( pVar->GetScopeLevel() != GetNowLevel() ) continue; if( pVar->IsByValStructParameter() ){ //構造体パラメータを持つとき //メモリを解放する #ifdef _AMD64_ //x64ビットコード //mov rcx,qword ptr[rsp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, -pVar->GetOffsetAddress(), MOD_BASE_DISP32, Schedule::None, true) ); #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( compiler.IsGlobalAreaCompiling() ){ //ここには来ないハズ compiler.errorMessenger.Output(300,NULL,cp); } } } if(indexSystemGC!=-1){ //_System_GCオブジェクトのデストラクタの呼び出し処理 const CMethod *method = (*pVariabls)[indexSystemGC]->GetType().GetClass().GetDestructorMethod(); if( method ){ Opcode_CallProc("",&method->GetUserProc(),0,(*pVariabls)[indexSystemGC]->GetName().c_str()); } } } // Returnステートメントで発行されるデストラクタを生成 void LexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ //現在のスコープレベルを退避 int backupScopeLevel = GetNowLevel(); for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ SetNowLevel( i ); CallDestructorsOfScopeEnd(); } //現在のスコープレベルを復元 SetNowLevel( backupScopeLevel ); }