source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/Exception.cpp@ 450

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

・コンストラクタを呼び出す前に動的型情報を用意するようにした。
・Foreachの一時オブジェクトの初期値をNothingにした(64bit)
・Catchステートメントのエラーメッセージを改修した。

File size: 10.6 KB
Line 
1#include "stdafx.h"
2
3#ifdef _AMD64_
4#include "../../BasicCompiler64/opcode.h"
5#else
6#include "../../BasicCompiler32/opcode.h"
7#endif
8
9#include <Exception.h>
10
11namespace Exception{
12
13class CatchScope
14{
15 Type paramType;
16 long codePos;
17public:
18 CatchScope( const Type &paramType, long codePos )
19 : paramType( paramType )
20 , codePos( codePos )
21 {
22 }
23 ~CatchScope()
24 {
25 }
26
27 const Type &GetParamType() const
28 {
29 return paramType;
30 }
31 long GetCodePos() const
32 {
33 return codePos;
34 }
35};
36typedef std::vector<CatchScope> CatchScopes;
37
38class TryScope
39{
40 int sourceCodePos;
41 bool isDefinedFinally;
42
43 CatchScopes catchScopes;
44
45 std::vector<const PertialSchedule *> finallySchedules;
46 void JmpFinally()
47 {
48 finallySchedules.push_back(
49 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
50 );
51 }
52 void ResolveJmpFinally()
53 {
54 BOOST_FOREACH( const PertialSchedule *pPertialSchedule, finallySchedules )
55 {
56 compiler.codeGenerator.opfix_JmpPertialSchedule( pPertialSchedule );
57 }
58 }
59
60 const PertialSchedule *pPertialScheduleForCatchAddress;
61 const PertialSchedule *pPertialScheduleForFinallyAddress;
62
63public:
64 TryScope( int sourceCodePos )
65 : sourceCodePos( sourceCodePos )
66 , isDefinedFinally( false )
67 {
68 }
69 ~TryScope()
70 {
71 }
72
73 int GetSourceCodePos() const
74 {
75 return sourceCodePos;
76 }
77 const CatchScopes &GetCatchScopes() const
78 {
79 return catchScopes;
80 }
81 bool IsCatched() const
82 {
83 return ( catchScopes.size() != 0 );
84 }
85 bool IsDefinedFinally() const
86 {
87 return isDefinedFinally;
88 }
89
90 void RegistPertialScheduleForCatchAddress( const PertialSchedule *pPertialScheduleForCatchAddress )
91 {
92 this->pPertialScheduleForCatchAddress = pPertialScheduleForCatchAddress;
93 }
94 const PertialSchedule *GetPertialScheduleForCatchAddress() const
95 {
96 return pPertialScheduleForCatchAddress;
97 }
98 void RegistPertialScheduleForFinallyAddress( const PertialSchedule *pPertialScheduleForFinallyAddress )
99 {
100 this->pPertialScheduleForFinallyAddress = pPertialScheduleForFinallyAddress;
101 }
102 const PertialSchedule *GetPertialScheduleForFinallyAddress() const
103 {
104 return pPertialScheduleForFinallyAddress;
105 }
106
107
108
109 void Try()
110 {
111 // レキシカルスコープをレベルアップ
112 compiler.codeGenerator.lexicalScopes.Start(
113 compiler.codeGenerator.GetNativeCodeSize(),
114 LexicalScope::SCOPE_TRY
115 );
116 }
117
118 void Catch( Type &paramType )
119 {
120 if( isDefinedFinally )
121 {
122 SetError(71,NULL,cp);
123 return;
124 }
125
126 if( catchScopes.size() )
127 {
128 // 既に1回以上のCatchが存在するとき
129
130 // レキシカルスコープをレベルダウン
131 compiler.codeGenerator.lexicalScopes.End();
132 }
133
134 JmpFinally();
135
136 catchScopes.push_back( CatchScope( paramType, compiler.codeGenerator.GetNativeCodeSize() ) );
137
138 // レキシカルスコープをレベルアップ
139 compiler.codeGenerator.lexicalScopes.Start(
140 compiler.codeGenerator.GetNativeCodeSize(),
141 LexicalScope::SCOPE_CATCH
142 );
143 }
144 void Finally()
145 {
146 if( isDefinedFinally )
147 {
148 SetError(70,NULL,cp);
149 return;
150 }
151
152 if( catchScopes.size() )
153 {
154 // 既に1回以上のCatchが存在するとき
155
156 // レキシカルスコープをレベルダウン
157 compiler.codeGenerator.lexicalScopes.End();
158 }
159
160 isDefinedFinally = true;
161
162 ResolveJmpFinally();
163
164 // レキシカルスコープをレベルアップ
165 compiler.codeGenerator.lexicalScopes.Start(
166 compiler.codeGenerator.GetNativeCodeSize(),
167 LexicalScope::SCOPE_FINALLY
168 );
169 }
170
171 void EndTry()
172 {
173 if( !isDefinedFinally )
174 {
175 SetError();
176 }
177
178 if( catchScopes.size() || isDefinedFinally )
179 {
180 // 既に1回以上のCatch、またはFinallyが存在するとき
181
182 // レキシカルスコープをレベルダウン
183 compiler.codeGenerator.lexicalScopes.End();
184 }
185
186 // レキシカルスコープをレベルダウン
187 compiler.codeGenerator.lexicalScopes.End();
188 }
189
190 int GenerateCatchTable()
191 {
192 int size = static_cast<int>(( (catchScopes.size()+1)*2 ) * sizeof(LONG_PTR));
193 BYTE *buffer = (BYTE *)calloc( size, 1 );
194
195 int pos = 0;
196 BOOST_FOREACH( const CatchScope &catchScope, catchScopes )
197 {
198 // パラメータのクラス名
199 char paramName[VN_SIZE] = "";
200 int paramNameDataTableOffset = 0;
201 if( catchScope.GetParamType().IsObject() )
202 {
203 lstrcpy( paramName, catchScope.GetParamType().GetClass().GetFullName().c_str() );
204 }
205 paramNameDataTableOffset = compiler.GetObjectModule().dataTable.AddString( paramName );
206 *((LONG_PTR *)(buffer+pos)) = paramNameDataTableOffset;
207 pos += sizeof(LONG_PTR);
208
209 // Catchアドレス
210 *((LONG_PTR *)(buffer+pos)) = catchScope.GetCodePos();
211 pos += sizeof(LONG_PTR);
212 }
213
214 int dataTableOffset = compiler.GetObjectModule().dataTable.AddBinary( buffer, size );
215
216 free( buffer );
217
218 pos = 0;
219 BOOST_FOREACH( const CatchScope &catchScope, catchScopes )
220 {
221 // パラメータのクラス名
222 compiler.GetObjectModule().dataTable.schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + pos ) );
223 pos += sizeof(LONG_PTR);
224
225 // Catchアドレス
226 const UserProc *pUserProc = &UserProc::CompilingUserProc();
227 if( UserProc::IsGlobalAreaCompiling() )
228 {
229 pUserProc = UserProc::pGlobalProc;
230 }
231 compiler.GetObjectModule().dataTable.schedules.push_back( Schedule( pUserProc, dataTableOffset + pos ) );
232 compiler.GetObjectModule().dataTable.schedules.back().SpecifyCatchAddress();
233 pos += sizeof(LONG_PTR);
234 }
235
236 return dataTableOffset;
237 }
238};
239typedef std::vector<TryScope> TryScopes;
240
241TryScopes tryScopes;
242
243void TryCommand()
244{
245 tryScopes.push_back( TryScope( cp ) );
246 tryScopes.back().Try();
247
248 int backCp = cp;
249
250 char temporary[1024];
251 lstrcpy( temporary, "ExceptionService.BeginTryScope( _System_GetNowScopeCatchAddresses() As VoidPtr, _System_GetNowScopeFinallyAddresses() As VoidPtr, _System_GetBp() As LONG_PTR, _System_GetSp() As LONG_PTR )" );
252 MakeMiddleCode( temporary );
253 ChangeOpcode( temporary );
254
255 cp = backCp;
256}
257void CatchCommand( const char *parameter )
258{
259 if( tryScopes.size() == 0 )
260 {
261 SetError(1,NULL,cp);
262 return;
263 }
264
265 char varName[VN_SIZE];
266 Type paramType;
267 if( parameter[0] )
268 {
269 char typeName[VN_SIZE];
270 SplitSyntacticForAs( parameter, varName, typeName );
271 if( !typeName[0] )
272 {
273 SetError(72,NULL,cp);
274 }
275 else
276 {
277 if( !compiler.StringToType( typeName, paramType ) )
278 {
279 SetError(74,typeName,cp);
280 }
281 else
282 {
283 if( !paramType.IsObject() )
284 {
285 SetError(73,typeName,cp);
286 }
287 }
288 }
289 }
290
291 tryScopes.back().Catch( paramType );
292
293 int backCp = cp;
294
295 char temporary[1024];
296 if( paramType.IsObject() )
297 {
298 sprintf( temporary, "Dim %s = Thread.CurrentThread().__GetThrowintParamObject() As %s", varName, paramType.GetClass().GetFullName().c_str() );
299 MakeMiddleCode( temporary );
300 ChangeOpcode( temporary );
301 }
302 lstrcpy( temporary, "Thread.CurrentThread().__Catched()" );
303 MakeMiddleCode( temporary );
304 ChangeOpcode( temporary );
305
306 cp = backCp;
307}
308void FinallyCommand()
309{
310 tryScopes.back().Finally();
311
312 int backCp = cp;
313
314 char temporary[1024];
315 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->FinishFinally()" );
316 MakeMiddleCode( temporary );
317 ChangeOpcode( temporary );
318
319 cp = backCp;
320
321 //Tryスコープに入るときに引き渡されるパラメータ値を解決
322 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForFinallyAddress(), compiler.codeGenerator.GetNativeCodeSize() );
323}
324void EndTryCommand( bool isNoWarning )
325{
326 if( tryScopes.size() == 0 )
327 {
328 SetError(12,"End Try",cp);
329 return;
330 }
331
332 if( !isNoWarning && !tryScopes.back().IsDefinedFinally() && !tryScopes.back().IsCatched() )
333 {
334 // CatchもFinallyも存在しないとき
335 SetError(-108,NULL,tryScopes.back().GetSourceCodePos() );
336 }
337
338 int dataTableOffset = tryScopes.back().GenerateCatchTable();
339
340 // _System_GetNowScopeCatchAddressesを解決
341 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForCatchAddress(), dataTableOffset );
342
343 if( !tryScopes.back().IsDefinedFinally() )
344 {
345 // Finallyが定義されていないときは空のFinallyを定義しておく
346 FinallyCommand();
347 }
348
349 int backCp = cp;
350
351 char temporary[1024];
352 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
353 MakeMiddleCode( temporary );
354 ChangeOpcode( temporary );
355
356 cp = backCp;
357
358 tryScopes.back().EndTry();
359 tryScopes.pop_back();
360}
361
362void InspectTryScope()
363{
364 while( tryScopes.size() > 0 )
365 {
366 SetError(22, "Try", tryScopes.back().GetSourceCodePos() );
367
368 EndTryCommand( true );
369 }
370}
371
372void ThrowCommand( const char *Parameter )
373{
374 int backCp = cp;
375
376 char temporary[1024];
377 if( Parameter[0] )
378 {
379 sprintf( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowWithParam(%s)", Parameter );
380 }
381 else
382 {
383 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowNoneParam()" );
384 }
385 MakeMiddleCode( temporary );
386 ChangeOpcode( temporary );
387
388 cp = backCp;
389}
390
391void Opcode_Func_System_GetNowScopeCatchAddress()
392{
393 if( tryScopes.size() == 0 )
394 {
395 SetError(1,NULL,cp);
396 return;
397 }
398
399#ifdef _WIN64
400 //mov rax,catchAddress
401 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::DataTable, true );
402#else
403 //mov eax,catchAddress
404 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::DataTable, true );
405#endif
406
407 tryScopes.back().RegistPertialScheduleForCatchAddress( pPertialSchedule );
408
409 /*
410 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
411
412#ifdef _WIN64
413 //mov rax,dataTableOffset
414 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
415#else
416 //mov eax,dataTableOffset
417 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
418#endif
419 */
420}
421
422void Opcode_Func_System_GetNowScopeFinallyAddress()
423{
424 if( tryScopes.size() == 0 )
425 {
426 SetError(1,NULL,cp);
427 return;
428 }
429
430#ifdef _WIN64
431 //mov rax,finallyAddress
432 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::CatchAddress, true );
433#else
434 //mov eax,finallyAddress
435 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::CatchAddress, true );
436#endif
437
438 tryScopes.back().RegistPertialScheduleForFinallyAddress( pPertialSchedule );
439
440 /*
441 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
442
443#ifdef _WIN64
444 //mov rax,dataTableOffset
445 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
446#else
447 //mov eax,dataTableOffset
448 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
449#endif
450 */
451}
452
453
454} // Exception
Note: See TracBrowser for help on using the repository browser.