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->GetType().IsStruct() && pVar->IsParameter() ){ |
---|
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 | } |
---|