| 1 | #include "stdafx.h" | 
|---|
| 2 |  | 
|---|
| 3 | #include <LexicalScope.h> | 
|---|
| 4 | #include <Compiler.h> | 
|---|
| 5 |  | 
|---|
| 6 | #include "../common.h" | 
|---|
| 7 |  | 
|---|
| 8 | #ifdef _AMD64_ | 
|---|
| 9 | #include "../../BasicCompiler64/opcode.h" | 
|---|
| 10 | #else | 
|---|
| 11 | #include "../../BasicCompiler32/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 | SetError(); | 
|---|
| 67 | return; | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | //デストラクタを呼ぶ | 
|---|
| 71 | CallDestructorsOfScopeEnd(); | 
|---|
| 72 |  | 
|---|
| 73 | Variables &vars = UserProc::IsGlobalAreaCompiling() ? | 
|---|
| 74 | compiler.GetObjectModule().meta.GetGlobalVars() : | 
|---|
| 75 | UserProc::CompilingUserProc().GetLocalVars(); | 
|---|
| 76 |  | 
|---|
| 77 | //使用済みローカル変数の生存チェックを外す | 
|---|
| 78 | BOOST_FOREACH( Variable *pVar, vars ){ | 
|---|
| 79 | if(pVar->bLiving&&pVar->GetScopeLevel()==level){ | 
|---|
| 80 | pVar->bLiving=0; | 
|---|
| 81 | pVar->SetScopeEndAddress( compiler.codeGenerator.GetNativeCodeSize() ); | 
|---|
| 82 | } | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 |  | 
|---|
| 86 | //スコープ抜け出しスケジュール | 
|---|
| 87 | ppScopes[level]->RunScheduleOfBreak(); | 
|---|
| 88 |  | 
|---|
| 89 |  | 
|---|
| 90 | //スコープレベルを下げる | 
|---|
| 91 | delete ppScopes[level]; | 
|---|
| 92 | level--; | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | // スコープ終了時のデストラクタ呼び出し | 
|---|
| 96 | void LexicalScopes::CallDestructorsOfScopeEnd(){ | 
|---|
| 97 |  | 
|---|
| 98 | Variables &vars = UserProc::IsGlobalAreaCompiling() ? | 
|---|
| 99 | compiler.GetObjectModule().meta.GetGlobalVars() : | 
|---|
| 100 | UserProc::CompilingUserProc().GetLocalVars(); | 
|---|
| 101 |  | 
|---|
| 102 |  | 
|---|
| 103 | int i3; | 
|---|
| 104 | int indexSystemGC=-1; | 
|---|
| 105 | for( i3 = (int)vars.size() - 1; i3 >= 0; i3-- ){        //確保したのと逆順序で解放するため、バックサーチにする | 
|---|
| 106 |  | 
|---|
| 107 | Variable *pVar = vars[i3]; | 
|---|
| 108 |  | 
|---|
| 109 | if( UserProc::IsGlobalAreaCompiling() && GetNowLevel() == 0 ){ | 
|---|
| 110 | if( pVar->GetName() == "_System_GC" ){ | 
|---|
| 111 | indexSystemGC=i3; | 
|---|
| 112 | continue; | 
|---|
| 113 | } | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | //同一レベルのレキシカルスコープのみを検知 | 
|---|
| 117 | if(!pVar->bLiving) continue; | 
|---|
| 118 | if( pVar->GetScopeLevel() != GetNowLevel() ) continue; | 
|---|
| 119 |  | 
|---|
| 120 | if( pVar->GetType().IsStruct() && pVar->IsParameter() ){ | 
|---|
| 121 | //構造体パラメータを持つとき | 
|---|
| 122 |  | 
|---|
| 123 | //メモリを解放する | 
|---|
| 124 |  | 
|---|
| 125 | #ifdef _AMD64_ | 
|---|
| 126 | //x64ビットコード | 
|---|
| 127 |  | 
|---|
| 128 | //mov rcx,qword ptr[rsp+offset] | 
|---|
| 129 | compiler.codeGenerator.localVarPertialSchedules.push_back( | 
|---|
| 130 | compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP, | 
|---|
| 131 | -pVar->GetOffsetAddress(), | 
|---|
| 132 | MOD_BASE_DISP32, | 
|---|
| 133 | Schedule::None, true) | 
|---|
| 134 | ); | 
|---|
| 135 | #else | 
|---|
| 136 | //x86コード | 
|---|
| 137 |  | 
|---|
| 138 | //mov ecx,dword ptr[ebp+offset] | 
|---|
| 139 | compiler.codeGenerator.localVarPertialSchedules.push_back( | 
|---|
| 140 | compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->GetOffsetAddress(),MOD_BASE_DISP32, Schedule::None, true ) | 
|---|
| 141 | ); | 
|---|
| 142 |  | 
|---|
| 143 | //push ecx | 
|---|
| 144 | compiler.codeGenerator.op_push(REG_ECX); | 
|---|
| 145 | #endif | 
|---|
| 146 |  | 
|---|
| 147 | //call free | 
|---|
| 148 | extern const UserProc *pSub_free; | 
|---|
| 149 | compiler.codeGenerator.op_call(pSub_free); | 
|---|
| 150 |  | 
|---|
| 151 |  | 
|---|
| 152 | if( UserProc::IsGlobalAreaCompiling() ){ | 
|---|
| 153 | //ここには来ないハズ | 
|---|
| 154 | SetError(300,NULL,cp); | 
|---|
| 155 | } | 
|---|
| 156 | } | 
|---|
| 157 | } | 
|---|
| 158 |  | 
|---|
| 159 | if(indexSystemGC!=-1){ | 
|---|
| 160 | //_System_GCオブジェクトのデストラクタの呼び出し処理 | 
|---|
| 161 | const CMethod *method = vars[indexSystemGC]->GetType().GetClass().GetDestructorMethod(); | 
|---|
| 162 | if( method ){ | 
|---|
| 163 | Opcode_CallProc("",&method->GetUserProc(),0,vars[indexSystemGC]->GetName().c_str(),DEF_OBJECT); | 
|---|
| 164 | } | 
|---|
| 165 | } | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | // Returnステートメントで発行されるデストラクタを生成 | 
|---|
| 169 | void LexicalScopes::CallDestructorsOfReturn( int BaseLevel ){ | 
|---|
| 170 | //現在のスコープレベルを退避 | 
|---|
| 171 | int backupScopeLevel = GetNowLevel(); | 
|---|
| 172 |  | 
|---|
| 173 | for( int i = GetNowLevel(); i >= BaseLevel; i-- ){ | 
|---|
| 174 | SetNowLevel( i ); | 
|---|
| 175 |  | 
|---|
| 176 | CallDestructorsOfScopeEnd(); | 
|---|
| 177 | } | 
|---|
| 178 |  | 
|---|
| 179 | //現在のスコープレベルを復元 | 
|---|
| 180 | SetNowLevel( backupScopeLevel ); | 
|---|
| 181 | } | 
|---|