source: dev/BasicCompiler_Common/LexicalScoping.cpp@ 108

Last change on this file since 108 was 75, checked in by dai_9181, 18 years ago

TYPEINFO→Typeへのリファクタリングを実施。64bitはほぼ完了。32bitが全般的に未完成。

File size: 5.2 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 Variables &vars = UserProc::IsGlobalAreaCompiling()?
88 globalVars :
89 UserProc::CompilingUserProc().localVars;
90
91 //使用済みローカル変数の生存チェックを外す
92 foreach( Variable *pVar, vars ){
93 if(pVar->bLiving&&pVar->ScopeLevel==level){
94 pVar->bLiving=0;
95 extern int obp;
96 pVar->ScopeEndAddress=obp;
97 }
98 }
99
100
101 //スコープ抜け出しスケジュール
102 ppScopes[level]->RunScheduleOfBreak();
103
104
105 //スコープレベルを下げる
106 delete ppScopes[level];
107 level--;
108}
109
110void CLexicalScopes::ExitFor(){
111 CScope *pScope = SearchScope( SCOPE_TYPE_FOR );
112 if( !pScope ){
113 SetError(12,"Exit For",cp);
114 return;
115 }
116
117 pScope->Break();
118}
119void CLexicalScopes::ExitWhile(){
120 CScope *pScope = SearchScope( SCOPE_TYPE_WHILE );
121 if( !pScope ){
122 SetError(12,"Exit While",cp);
123 return;
124 }
125
126 pScope->Break();
127}
128void CLexicalScopes::ExitDo(){
129 CScope *pScope = SearchScope( SCOPE_TYPE_DO );
130 if( !pScope ){
131 SetError(12,"Exit Do",cp);
132 return;
133 }
134
135 pScope->Break();
136}
137
138int CLexicalScopes::GetNowLevel(){
139 return level;
140}
141void CLexicalScopes::SetNowLevel( int level ){
142 this->level = level;
143}
144int CLexicalScopes::GetStartAddress(){
145 return ppScopes[level]->GetStartAddress();
146}
147
148
149// スコープ終了時のデストラクタ呼び出し
150void CLexicalScopes::CallDestructorsOfScopeEnd(){
151
152 Variables &vars = UserProc::IsGlobalAreaCompiling()?
153 globalVars :
154 UserProc::CompilingUserProc().localVars;
155
156
157 int i3;
158 int indexSystemGC=-1;
159 for( i3 = (int)vars.size() - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする
160
161 Variable *pVar = vars[i3];
162
163 if( UserProc::IsGlobalAreaCompiling() && GetNowLevel() == 0 ){
164 if( pVar->GetName() == "_System_GC" ){
165 indexSystemGC=i3;
166 continue;
167 }
168 }
169
170 //同一レベルのレキシカルスコープのみを検知
171 if(!pVar->bLiving) continue;
172 if( pVar->ScopeLevel != GetNowLevel() ) continue;
173
174 if( pVar->IsStruct() && pVar->IsParameter() ){
175 //構造体パラメータを持つとき
176
177 //メモリを解放する
178
179#ifdef _AMD64_
180 //x64ビットコード
181
182 //mov rcx,qword ptr[rsp+offset]
183 op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
184 -pVar->offset,
185 MOD_BASE_DISP32);
186 obp-=sizeof(long);
187 AddLocalVarAddrSchedule();
188 obp+=sizeof(long);
189#else
190 //x86コード
191
192 //mov ecx,dword ptr[ebp+offset]
193 op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->offset,MOD_BASE_DISP32);
194 obp-=sizeof(long);
195 AddLocalVarAddrSchedule();
196 obp+=sizeof(long);
197
198 //push ecx
199 op_push(REG_ECX);
200#endif
201
202 //call free
203 extern UserProc *pSub_free;
204 op_call(pSub_free);
205
206
207 if( UserProc::IsGlobalAreaCompiling() ){
208 //ここには来ないハズ
209 SetError(300,NULL,cp);
210 }
211 }
212 }
213
214 if(indexSystemGC!=-1){
215 //_System_GCオブジェクトのデストラクタの呼び出し処理
216 CMethod *method = vars[indexSystemGC]->GetClass().GetDestructorMethod();
217 if( method ){
218 Opcode_CallProc("",method->pUserProc,0,vars[indexSystemGC]->GetName().c_str(),DEF_OBJECT);
219 }
220 }
221}
222
223// Returnステートメントで発行されるデストラクタを生成
224void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
225 //現在のスコープレベルを退避
226 int backupScopeLevel = GetNowLevel();
227
228 for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
229 SetNowLevel( i );
230
231 CallDestructorsOfScopeEnd();
232 }
233
234 //現在のスコープレベルを復元
235 SetNowLevel( backupScopeLevel );
236}
Note: See TracBrowser for help on using the repository browser.