source: dev/BasicCompiler_Common/LexicalScoping.cpp@ 64

Last change on this file since 64 was 64, checked in by dai_9181, 17 years ago

すべてのオブジェクトを参照型に切り替えた。

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