source: dev/BasicCompiler_Common/LexicalScoping.cpp@ 60

Last change on this file since 60 was 51, checked in by dai_9181, 18 years ago

ppobj_Member及びppobj_StaticMemberを廃止し、vectorに統一した(methods及びstaticMethods)。

File size: 7.0 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;
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 CMethod *method = pVar[i3].u.pobj_c->GetDestructorMethod();
204 if( method ){
205 Opcode_CallProc("", method->psi,0,pVar[i3].name,DEF_OBJECT);
206 }
207
208 //メモリを解放する
209
210#ifdef _AMD64_
211 //x64ビットコード
212
213 //mov rcx,qword ptr[rsp+offset]
214 op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
215 -pVar[i3].offset,
216 MOD_BASE_DISP32);
217 obp-=sizeof(long);
218 AddLocalVarAddrSchedule();
219 obp+=sizeof(long);
220#else
221 //x86コード
222
223 //mov ecx,dword ptr[ebp+offset]
224 op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32);
225 obp-=sizeof(long);
226 AddLocalVarAddrSchedule();
227 obp+=sizeof(long);
228
229 //push ecx
230 op_push(REG_ECX);
231#endif
232
233 //call free
234 extern SUBINFO *pSub_free;
235 op_call(pSub_free);
236
237
238 if(bCompilingGlobal){
239 //ここには来ないハズ
240 SetError(300,NULL,cp);
241 }
242 }
243 else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){
244 //デストラクタの呼び出し
245 CMethod *method = pVar[i3].u.pobj_c->GetDestructorMethod();
246 if( method ){
247 int ss[MAX_ARRAYDIM];
248 memset(ss,0,MAX_ARRAYDIM*sizeof(int));
249 if(pVar[i3].SubScripts[0]!=-1){
250 while(1){
251 for(i4=0;;i4++){
252 if(pVar[i3].SubScripts[i4]==-1) break;
253
254 if(ss[i4]>pVar[i3].SubScripts[i4]){
255 ss[i4]=0;
256 ss[i4+1]++;
257 }
258 else break;
259 }
260 if(pVar[i3].SubScripts[i4]==-1) break;
261 char temporary[VN_SIZE];
262 sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]);
263 for(i4=1;;i4++){
264 if(pVar[i3].SubScripts[i4]==-1) break;
265
266 sprintf(temporary+lstrlen(temporary),",%d",ss[i4]);
267 }
268 lstrcat(temporary,"]");
269 Opcode_CallProc("",method->psi,0,temporary,DEF_OBJECT);
270
271 ss[0]++;
272
273
274 //ネイティブコードバッファの再確保
275 extern int obp_AllocSize;
276 if(obp_AllocSize<obp+8192){
277 obp_AllocSize+=8192;
278 OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
279 }
280 }
281 }
282 else{
283 Opcode_CallProc("",method->psi,0,pVar[i3].name,DEF_OBJECT);
284 }
285 }
286 }
287 }
288
289 if(indexSystemGC!=-1){
290 //_System_GCオブジェクトのデストラクタの呼び出し処理
291 CMethod *method = pVar[indexSystemGC].u.pobj_c->GetDestructorMethod();
292 if( method ){
293 Opcode_CallProc("",method->psi,0,pVar[indexSystemGC].name,DEF_OBJECT);
294 }
295 }
296}
297
298// Returnステートメントで発行されるデストラクタを生成
299void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
300 //現在のスコープレベルを退避
301 int backupScopeLevel = GetNowLevel();
302
303 for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
304 SetNowLevel( i );
305
306 CallDestructorsOfScopeEnd();
307 }
308
309 //現在のスコープレベルを復元
310 SetNowLevel( backupScopeLevel );
311}
Note: See TracBrowser for help on using the repository browser.