source: dev/BasicCompiler_Common/LexicalScoping.cpp@ 37

Last change on this file since 37 was 34, checked in by dai_9181, 18 years ago

スコープ処理を統一した。関数の途中でReturnしても、スコープにあるローカルオブジェクトを正確に破棄できるようにした。

File size: 7.1 KB
Line 
1#include "common.h"
2#ifdef _AMD64_
3#include "../BasicCompiler64/opcode.h"
4#else
5#include "../BasicCompiler32/opcode.h"
6#endif
7
8
9CLexicalScopes obj_LexScopes;
10
11
12CScope::CScope( int level, int addr, SCOPE_TYPE TypeOfStatement ){
13 this->level = level;
14 this->StartAddress = addr;
15 this->TypeOfStatement = TypeOfStatement;
16
17 pBreakSchedule = (DWORD *)malloc( 1 );
18 nBreakSchedule = 0;
19}
20CScope::~CScope(){
21 free( pBreakSchedule );
22}
23
24int CScope::GetStartAddress(){
25 return StartAddress;
26}
27SCOPE_TYPE CScope::GetTypeOfStatement(){
28 return TypeOfStatement;
29}
30
31void CScope::Break(){
32 //未解放のローカルオブジェクトを解放する
33 obj_LexScopes.CallDestructorsOfReturn( level );
34
35 //jmp ...(Next addr)
36 OpBuffer[obp++]=(char)0xE9;
37
38 pBreakSchedule=(DWORD *)realloc( pBreakSchedule, ( nBreakSchedule + 1 ) * sizeof(DWORD) );
39 pBreakSchedule[nBreakSchedule]=obp;
40 nBreakSchedule++;
41
42 obp+=sizeof(long);
43}
44void CScope::RunScheduleOfBreak(){
45 for(int i=0;i<nBreakSchedule;i++){
46 *((long *)(OpBuffer+pBreakSchedule[i]))=obp-(pBreakSchedule[i]+sizeof(long));
47 }
48}
49
50
51CScope *CLexicalScopes::SearchScope( SCOPE_TYPE TypeOfStatement ){
52 for( int i = level; i>=0; i-- ){
53 if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){
54 return ppScopes[i];
55 }
56 }
57 return NULL;
58}
59
60CLexicalScopes::CLexicalScopes(){
61 ppScopes = (CScope **)malloc( 1 );
62 level=0;
63}
64CLexicalScopes::~CLexicalScopes(){
65 free( ppScopes );
66}
67void CLexicalScopes::Init(int addr){
68 // TODO: エラーチェック
69
70 level = -1;
71 Start( addr, SCOPE_TYPE_BASE );
72}
73void CLexicalScopes::Start( int addr, SCOPE_TYPE TypeOfStatement ){
74 level++;
75 ppScopes = (CScope **)realloc( ppScopes, ( level + 1 ) * sizeof( CScope * ) );
76 ppScopes[level] = new CScope( level, addr, TypeOfStatement );
77}
78void CLexicalScopes::End(){
79 if( level <= 0 ){
80 SetError(300,NULL,cp);
81 return;
82 }
83
84 //デストラクタを呼ぶ
85 CallDestructorsOfScopeEnd();
86
87 extern BOOL bCompilingGlobal;
88 VARIABLE *pVar;
89 int num;
90 if(bCompilingGlobal){
91 //グローバル領域をコンパイルしているとき
92 extern VARIABLE *GlobalVar;
93 extern int MaxGlobalVarNum;
94 pVar=GlobalVar;
95 num=MaxGlobalVarNum;
96 }
97 else{
98 //ローカル領域をコンパイルしているとき
99 extern VARIABLE *LocalVar;
100 extern int MaxLocalVarNum;
101 pVar=LocalVar;
102 num=MaxLocalVarNum;
103 }
104
105 //使用済みローカル変数の生存チェックを外す
106 for(int i=0;i<num;i++){
107 if(pVar[i].bLiving&&pVar[i].ScopeLevel==level){
108 pVar[i].bLiving=0;
109 extern int obp;
110 pVar[i].ScopeEndAddress=obp;
111 }
112 }
113
114
115 //スコープ抜け出しスケジュール
116 ppScopes[level]->RunScheduleOfBreak();
117
118
119 //スコープレベルを下げる
120 delete ppScopes[level];
121 level--;
122}
123
124void CLexicalScopes::ExitFor(){
125 CScope *pScope = SearchScope( SCOPE_TYPE_FOR );
126 if( !pScope ){
127 SetError(12,"Exit For",cp);
128 return;
129 }
130
131 pScope->Break();
132}
133void CLexicalScopes::ExitWhile(){
134 CScope *pScope = SearchScope( SCOPE_TYPE_WHILE );
135 if( !pScope ){
136 SetError(12,"Exit While",cp);
137 return;
138 }
139
140 pScope->Break();
141}
142void CLexicalScopes::ExitDo(){
143 CScope *pScope = SearchScope( SCOPE_TYPE_DO );
144 if( !pScope ){
145 SetError(12,"Exit Do",cp);
146 return;
147 }
148
149 pScope->Break();
150}
151
152int CLexicalScopes::GetNowLevel(){
153 return level;
154}
155void CLexicalScopes::SetNowLevel( int level ){
156 this->level = level;
157}
158int CLexicalScopes::GetStartAddress(){
159 return ppScopes[level]->GetStartAddress();
160}
161
162
163// スコープ終了時のデストラクタ呼び出し
164void CLexicalScopes::CallDestructorsOfScopeEnd(){
165 extern BOOL bCompilingGlobal;
166 VARIABLE *pVar;
167 int num;
168 if(bCompilingGlobal){
169 //グローバルオブジェクトの解放処理
170 extern VARIABLE *GlobalVar;
171 extern int MaxGlobalVarNum;
172 pVar=GlobalVar;
173 num=MaxGlobalVarNum;
174 }
175 else{
176 //ローカルオブジェクトの解放処理
177 extern VARIABLE *LocalVar;
178 extern int MaxLocalVarNum;
179 pVar=LocalVar;
180 num=MaxLocalVarNum;
181 }
182
183
184 int i3,i4,i5;
185 int indexSystemGC=-1;
186 for( i3 = num - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする
187
188 if( bCompilingGlobal && GetNowLevel() == 0 ){
189 if(lstrcmp(pVar[i3].name,"_System_GC")==0){
190 indexSystemGC=i3;
191 continue;
192 }
193 }
194
195 //同一レベルのレキシカルスコープのみを検知
196 if(!pVar[i3].bLiving) continue;
197 if( pVar[i3].ScopeLevel != GetNowLevel() ) continue;
198
199 if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef&OBJECT_PARAMETER){
200 //実態オブジェクトのパラメータを持つとき
201
202 //デストラクタを呼び出す
203 i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
204 if(i5!=-1)
205 Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
206
207 //メモリを解放する
208
209#ifdef _AMD64_
210 //x64ビットコード
211
212 //mov rcx,qword ptr[rsp+offset]
213 op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
214 -pVar[i3].offset,
215 MOD_BASE_DISP32);
216 obp-=sizeof(long);
217 AddLocalVarAddrSchedule();
218 obp+=sizeof(long);
219#else
220 //x86コード
221
222 //mov ecx,dword ptr[ebp+offset]
223 op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32);
224 obp-=sizeof(long);
225 AddLocalVarAddrSchedule();
226 obp+=sizeof(long);
227
228 //push ecx
229 op_push(REG_ECX);
230#endif
231
232 //call free
233 extern SUBINFO *pSub_free;
234 op_call(pSub_free);
235
236
237 if(bCompilingGlobal){
238 //ここには来ないハズ
239 SetError(300,NULL,cp);
240 }
241 }
242 else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){
243 //デストラクタの呼び出し
244 i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
245 if(i5!=-1){
246 int ss[MAX_ARRAYDIM];
247 memset(ss,0,MAX_ARRAYDIM*sizeof(int));
248 if(pVar[i3].SubScripts[0]!=-1){
249 while(1){
250 for(i4=0;;i4++){
251 if(pVar[i3].SubScripts[i4]==-1) break;
252
253 if(ss[i4]>pVar[i3].SubScripts[i4]){
254 ss[i4]=0;
255 ss[i4+1]++;
256 }
257 else break;
258 }
259 if(pVar[i3].SubScripts[i4]==-1) break;
260 char temporary[VN_SIZE];
261 sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]);
262 for(i4=1;;i4++){
263 if(pVar[i3].SubScripts[i4]==-1) break;
264
265 sprintf(temporary+lstrlen(temporary),",%d",ss[i4]);
266 }
267 lstrcat(temporary,"]");
268 Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,temporary,DEF_OBJECT);
269
270 ss[0]++;
271
272
273 //ネイティブコードバッファの再確保
274 extern int obp_AllocSize;
275 if(obp_AllocSize<obp+8192){
276 obp_AllocSize+=8192;
277 OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
278 }
279 }
280 }
281 else{
282 Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
283 }
284 }
285 }
286 }
287
288 if(indexSystemGC!=-1){
289 //_System_GCオブジェクトのデストラクタの呼び出し処理
290 i3=pVar[indexSystemGC].u.pobj_c->DestructorMemberSubIndex;
291 if(i3!=-1){
292 Opcode_CallProc("",pVar[indexSystemGC].u.pobj_c->ppobj_Method[i3]->psi,0,pVar[indexSystemGC].name,DEF_OBJECT);
293 }
294 }
295}
296
297// Returnステートメントで発行されるデストラクタを生成
298void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
299 //現在のスコープレベルを退避
300 int backupScopeLevel = GetNowLevel();
301
302 for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
303 SetNowLevel( i );
304
305 CallDestructorsOfScopeEnd();
306 }
307
308 //現在のスコープレベルを復元
309 SetNowLevel( backupScopeLevel );
310}
Note: See TracBrowser for help on using the repository browser.