| 1 | #include "stdafx.h" | 
|---|
| 2 |  | 
|---|
| 3 | #include <LexicalScope.h> | 
|---|
| 4 | #include <Compiler.h> | 
|---|
| 5 |  | 
|---|
| 6 | #include "../common.h" | 
|---|
| 7 |  | 
|---|
| 8 | #ifdef _AMD64_ | 
|---|
| 9 | #include "../../compiler_x64/opcode.h" | 
|---|
| 10 | #else | 
|---|
| 11 | #include "../../compiler_x86/opcode.h" | 
|---|
| 12 | #endif | 
|---|
| 13 |  | 
|---|
| 14 |  | 
|---|
| 15 | void LexicalScope::Break(){ | 
|---|
| 16 | //未解放のローカルオブジェクトを解放する | 
|---|
| 17 | compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn( level ); | 
|---|
| 18 |  | 
|---|
| 19 | //jmp ...(Next addr) | 
|---|
| 20 | breakPertialSchedules.push_back( | 
|---|
| 21 | compiler.codeGenerator.op_jmp( 0, sizeof(long), true ) | 
|---|
| 22 | ); | 
|---|
| 23 | } | 
|---|
| 24 | void LexicalScope::RunScheduleOfBreak(){ | 
|---|
| 25 | BOOST_FOREACH( const PertialSchedule *pBreakPertialSchedule, breakPertialSchedules ) | 
|---|
| 26 | { | 
|---|
| 27 | compiler.codeGenerator.opfix_JmpPertialSchedule( pBreakPertialSchedule ); | 
|---|
| 28 | } | 
|---|
| 29 | } | 
|---|
| 30 |  | 
|---|
| 31 |  | 
|---|
| 32 |  | 
|---|
| 33 | LexicalScope *LexicalScopes::SearchScope( LexicalScope::SCOPE_TYPE TypeOfStatement ){ | 
|---|
| 34 | for( int i = level; i>=0; i-- ){ | 
|---|
| 35 | if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){ | 
|---|
| 36 | return ppScopes[i]; | 
|---|
| 37 | } | 
|---|
| 38 | } | 
|---|
| 39 | return NULL; | 
|---|
| 40 | } | 
|---|
| 41 |  | 
|---|
| 42 | void LexicalScopes::Init(int addr){ | 
|---|
| 43 | // TODO: エラーチェック | 
|---|
| 44 |  | 
|---|
| 45 | level = -1; | 
|---|
| 46 | Start( addr, LexicalScope::SCOPE_TYPE_BASE ); | 
|---|
| 47 | } | 
|---|
| 48 | void LexicalScopes::Start( int addr, LexicalScope::SCOPE_TYPE TypeOfStatement ){ | 
|---|
| 49 | level++; | 
|---|
| 50 | ppScopes = (LexicalScope **)realloc( ppScopes, ( level + 1 ) * sizeof( LexicalScope * ) ); | 
|---|
| 51 | ppScopes[level] = new LexicalScope( level, addr, TypeOfStatement ); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | int LexicalScopes::GetNowLevel(){ | 
|---|
| 55 | return level; | 
|---|
| 56 | } | 
|---|
| 57 | void LexicalScopes::SetNowLevel( int level ){ | 
|---|
| 58 | this->level = level; | 
|---|
| 59 | } | 
|---|
| 60 | int LexicalScopes::GetStartAddress(){ | 
|---|
| 61 | return ppScopes[level]->GetStartAddress(); | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | void LexicalScopes::End(){ | 
|---|
| 65 | if( level <= 0 ){ | 
|---|
| 66 | compiler.errorMessenger.OutputFatalError(); | 
|---|
| 67 | return; | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | //デストラクタを呼ぶ | 
|---|
| 71 | CallDestructorsOfScopeEnd(); | 
|---|
| 72 |  | 
|---|
| 73 | Variables *pVars = compiler.IsGlobalAreaCompiling() ? | 
|---|
| 74 | &compiler.GetObjectModule().meta.GetGlobalVars() : | 
|---|
| 75 | &compiler.GetCompilingUserProc().GetLocalVars(); | 
|---|
| 76 |  | 
|---|
| 77 | //使用済みローカル変数の生存チェックを外す | 
|---|
| 78 | BOOST_FOREACH( Variable *pVar, (*pVars) ) | 
|---|
| 79 | { | 
|---|
| 80 | if( pVar->isLiving && pVar->GetScopeLevel() == level ) | 
|---|
| 81 | { | 
|---|
| 82 | pVar->isLiving = false; | 
|---|
| 83 | pVar->SetScopeEndAddress( compiler.codeGenerator.GetNativeCodeSize() ); | 
|---|
| 84 | } | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 |  | 
|---|
| 88 | //スコープ抜け出しスケジュール | 
|---|
| 89 | ppScopes[level]->RunScheduleOfBreak(); | 
|---|
| 90 |  | 
|---|
| 91 |  | 
|---|
| 92 | //スコープレベルを下げる | 
|---|
| 93 | delete ppScopes[level]; | 
|---|
| 94 | level--; | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | // スコープ終了時のデストラクタ呼び出し | 
|---|
| 98 | void LexicalScopes::CallDestructorsOfScopeEnd(){ | 
|---|
| 99 |  | 
|---|
| 100 | Variables *pVariabls = compiler.IsGlobalAreaCompiling() ? | 
|---|
| 101 | &compiler.GetObjectModule().meta.GetGlobalVars() : | 
|---|
| 102 | &compiler.GetCompilingUserProc().GetLocalVars(); | 
|---|
| 103 |  | 
|---|
| 104 |  | 
|---|
| 105 | int i3; | 
|---|
| 106 | int indexSystemGC=-1; | 
|---|
| 107 | for( i3 = (int)pVariabls->size() - 1; i3 >= 0; i3-- ){      //確保したのと逆順序で解放するため、バックサーチにする | 
|---|
| 108 |  | 
|---|
| 109 | Variable *pVar = (*pVariabls)[i3]; | 
|---|
| 110 |  | 
|---|
| 111 | if( compiler.IsGlobalAreaCompiling() && GetNowLevel() == 0 ){ | 
|---|
| 112 | if( pVar->GetName() == "_System_GC" ){ | 
|---|
| 113 | indexSystemGC=i3; | 
|---|
| 114 | continue; | 
|---|
| 115 | } | 
|---|
| 116 | } | 
|---|
| 117 |  | 
|---|
| 118 | //同一レベルのレキシカルスコープのみを検知 | 
|---|
| 119 | if( !pVar->isLiving ) continue; | 
|---|
| 120 | if( pVar->GetScopeLevel() != GetNowLevel() ) continue; | 
|---|
| 121 |  | 
|---|
| 122 | if( pVar->IsByValStructParameter() ){ | 
|---|
| 123 | //構造体パラメータを持つとき | 
|---|
| 124 |  | 
|---|
| 125 | //メモリを解放する | 
|---|
| 126 |  | 
|---|
| 127 | #ifdef _AMD64_ | 
|---|
| 128 | //x64ビットコード | 
|---|
| 129 |  | 
|---|
| 130 | //mov rcx,qword ptr[rsp+offset] | 
|---|
| 131 | compiler.codeGenerator.localVarPertialSchedules.push_back( | 
|---|
| 132 | compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, | 
|---|
| 133 | -pVar->GetOffsetAddress(), | 
|---|
| 134 | MOD_BASE_DISP32, | 
|---|
| 135 | Schedule::None, true) | 
|---|
| 136 | ); | 
|---|
| 137 | #else | 
|---|
| 138 | //x86コード | 
|---|
| 139 |  | 
|---|
| 140 | //mov ecx,dword ptr[ebp+offset] | 
|---|
| 141 | compiler.codeGenerator.localVarPertialSchedules.push_back( | 
|---|
| 142 | compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->GetOffsetAddress(),MOD_BASE_DISP32, Schedule::None, true ) | 
|---|
| 143 | ); | 
|---|
| 144 |  | 
|---|
| 145 | //push ecx | 
|---|
| 146 | compiler.codeGenerator.op_push(REG_ECX); | 
|---|
| 147 | #endif | 
|---|
| 148 |  | 
|---|
| 149 | //call free | 
|---|
| 150 | extern const UserProc *pSub_free; | 
|---|
| 151 | compiler.codeGenerator.op_call(pSub_free); | 
|---|
| 152 |  | 
|---|
| 153 |  | 
|---|
| 154 | if( compiler.IsGlobalAreaCompiling() ){ | 
|---|
| 155 | //ここには来ないハズ | 
|---|
| 156 | compiler.errorMessenger.Output(300,NULL,cp); | 
|---|
| 157 | } | 
|---|
| 158 | } | 
|---|
| 159 | } | 
|---|
| 160 |  | 
|---|
| 161 | if(indexSystemGC!=-1){ | 
|---|
| 162 | //_System_GCオブジェクトのデストラクタの呼び出し処理 | 
|---|
| 163 | const CMethod *method = (*pVariabls)[indexSystemGC]->GetType().GetClass().GetDestructorMethod(); | 
|---|
| 164 | if( method ){ | 
|---|
| 165 | Opcode_CallProc("",&method->GetUserProc(),0,(*pVariabls)[indexSystemGC]->GetName().c_str()); | 
|---|
| 166 | } | 
|---|
| 167 | } | 
|---|
| 168 | } | 
|---|
| 169 |  | 
|---|
| 170 | // Returnステートメントで発行されるデストラクタを生成 | 
|---|
| 171 | void LexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ | 
|---|
| 172 | //現在のスコープレベルを退避 | 
|---|
| 173 | int backupScopeLevel = GetNowLevel(); | 
|---|
| 174 |  | 
|---|
| 175 | for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ | 
|---|
| 176 | SetNowLevel( i ); | 
|---|
| 177 |  | 
|---|
| 178 | CallDestructorsOfScopeEnd(); | 
|---|
| 179 | } | 
|---|
| 180 |  | 
|---|
| 181 | //現在のスコープレベルを復元 | 
|---|
| 182 | SetNowLevel( backupScopeLevel ); | 
|---|
| 183 | } | 
|---|