source: dev/trunk/abdev/BasicCompiler_Common/src/Exception.cpp@ 420

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

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

File size: 10.6 KB
RevLine 
[206]1#include "stdafx.h"
2
[357]3#ifdef _AMD64_
4#include "../../BasicCompiler64/opcode.h"
5#else
6#include "../../BasicCompiler32/opcode.h"
7#endif
8
[125]9#include <Exception.h>
[52]10
11namespace Exception{
12
[361]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
[357]38class TryScope
39{
[365]40 int sourceCodePos;
[359]41 bool isDefinedFinally;
42
[361]43 CatchScopes catchScopes;
44
[359]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
[361]60 const PertialSchedule *pPertialScheduleForCatchAddress;
[359]61 const PertialSchedule *pPertialScheduleForFinallyAddress;
62
[357]63public:
[365]64 TryScope( int sourceCodePos )
65 : sourceCodePos( sourceCodePos )
66 , isDefinedFinally( false )
[357]67 {
68 }
69 ~TryScope()
70 {
71 }
[52]72
[365]73 int GetSourceCodePos() const
74 {
75 return sourceCodePos;
76 }
[361]77 const CatchScopes &GetCatchScopes() const
78 {
79 return catchScopes;
80 }
[359]81 bool IsCatched() const
82 {
[361]83 return ( catchScopes.size() != 0 );
[359]84 }
85 bool IsDefinedFinally() const
86 {
87 return isDefinedFinally;
88 }
89
[357]90 void RegistPertialScheduleForCatchAddress( const PertialSchedule *pPertialScheduleForCatchAddress )
91 {
92 this->pPertialScheduleForCatchAddress = pPertialScheduleForCatchAddress;
93 }
[361]94 const PertialSchedule *GetPertialScheduleForCatchAddress() const
95 {
96 return pPertialScheduleForCatchAddress;
97 }
[359]98 void RegistPertialScheduleForFinallyAddress( const PertialSchedule *pPertialScheduleForFinallyAddress )
99 {
100 this->pPertialScheduleForFinallyAddress = pPertialScheduleForFinallyAddress;
101 }
102 const PertialSchedule *GetPertialScheduleForFinallyAddress() const
103 {
104 return pPertialScheduleForFinallyAddress;
105 }
106
107
[357]108
[359]109 void Try()
[357]110 {
[364]111 // レキシカルスコープをレベルアップ
112 compiler.codeGenerator.lexicalScopes.Start(
113 compiler.codeGenerator.GetNativeCodeSize(),
114 LexicalScope::SCOPE_TRY
115 );
[357]116 }
117
[361]118 void Catch( Type &paramType )
[359]119 {
120 if( isDefinedFinally )
121 {
122 SetError(71,NULL,cp);
123 return;
124 }
125
[364]126 if( catchScopes.size() )
127 {
128 // 既に1回以上のCatchが存在するとき
129
130 // レキシカルスコープをレベルダウン
131 compiler.codeGenerator.lexicalScopes.End();
132 }
133
[361]134 JmpFinally();
[359]135
[361]136 catchScopes.push_back( CatchScope( paramType, compiler.codeGenerator.GetNativeCodeSize() ) );
[364]137
138 // レキシカルスコープをレベルアップ
139 compiler.codeGenerator.lexicalScopes.Start(
140 compiler.codeGenerator.GetNativeCodeSize(),
141 LexicalScope::SCOPE_CATCH
142 );
[359]143 }
144 void Finally()
145 {
146 if( isDefinedFinally )
147 {
148 SetError(70,NULL,cp);
149 return;
150 }
151
[364]152 if( catchScopes.size() )
153 {
154 // 既に1回以上のCatchが存在するとき
155
156 // レキシカルスコープをレベルダウン
157 compiler.codeGenerator.lexicalScopes.End();
158 }
159
[359]160 isDefinedFinally = true;
161
162 ResolveJmpFinally();
[364]163
164 // レキシカルスコープをレベルアップ
165 compiler.codeGenerator.lexicalScopes.Start(
166 compiler.codeGenerator.GetNativeCodeSize(),
167 LexicalScope::SCOPE_FINALLY
168 );
[359]169 }
170
[357]171 void EndTry()
172 {
[359]173 if( !isDefinedFinally )
174 {
[371]175 SetError();
[359]176 }
[364]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();
[357]188 }
[361]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アドレス
[364]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 ) );
[361]232 compiler.GetObjectModule().dataTable.schedules.back().SpecifyCatchAddress();
233 pos += sizeof(LONG_PTR);
234 }
235
236 return dataTableOffset;
237 }
[357]238};
239typedef std::vector<TryScope> TryScopes;
240
241TryScopes tryScopes;
242
243void TryCommand()
244{
[365]245 tryScopes.push_back( TryScope( cp ) );
[359]246 tryScopes.back().Try();
[357]247
248 int backCp = cp;
249
250 char temporary[1024];
[359]251 lstrcpy( temporary, "ExceptionService.BeginTryScope( _System_GetNowScopeCatchAddresses() As VoidPtr, _System_GetNowScopeFinallyAddresses() As VoidPtr, _System_GetBp() As LONG_PTR, _System_GetSp() As LONG_PTR )" );
[357]252 MakeMiddleCode( temporary );
253 ChangeOpcode( temporary );
254
255 cp = backCp;
[52]256}
[359]257void CatchCommand( const char *parameter )
[357]258{
259 if( tryScopes.size() == 0 )
260 {
261 SetError(1,NULL,cp);
262 return;
263 }
264
[364]265 char varName[VN_SIZE];
[359]266 Type paramType;
267 if( parameter[0] )
268 {
[364]269 char typeName[VN_SIZE];
[359]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 {
[391]279 SetError(74,typeName,cp);
[359]280 }
[391]281 else
282 {
283 if( !paramType.IsObject() )
284 {
285 SetError(73,typeName,cp);
286 }
287 }
[359]288 }
289 }
290
[361]291 tryScopes.back().Catch( paramType );
[364]292
[371]293 int backCp = cp;
294
295 char temporary[1024];
[364]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 );
[371]301 }
302 lstrcpy( temporary, "Thread.CurrentThread().__Catched()" );
303 MakeMiddleCode( temporary );
304 ChangeOpcode( temporary );
[364]305
[371]306 cp = backCp;
[52]307}
[357]308void FinallyCommand()
309{
[359]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() );
[52]323}
[366]324void EndTryCommand( bool isNoWarning )
[357]325{
326 if( tryScopes.size() == 0 )
327 {
[366]328 SetError(12,"End Try",cp);
[357]329 return;
330 }
331
[366]332 if( !isNoWarning && !tryScopes.back().IsDefinedFinally() && !tryScopes.back().IsCatched() )
[365]333 {
334 // CatchもFinallyも存在しないとき
335 SetError(-108,NULL,tryScopes.back().GetSourceCodePos() );
336 }
337
[361]338 int dataTableOffset = tryScopes.back().GenerateCatchTable();
[357]339
[361]340 // _System_GetNowScopeCatchAddressesを解決
341 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForCatchAddress(), dataTableOffset );
[359]342
343 if( !tryScopes.back().IsDefinedFinally() )
344 {
345 // Finallyが定義されていないときは空のFinallyを定義しておく
346 FinallyCommand();
347 }
348
[361]349 int backCp = cp;
350
[357]351 char temporary[1024];
352 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
353 MakeMiddleCode( temporary );
354 ChangeOpcode( temporary );
355
356 cp = backCp;
357
[359]358 tryScopes.back().EndTry();
[357]359 tryScopes.pop_back();
[52]360}
361
[366]362void InspectTryScope()
363{
364 while( tryScopes.size() > 0 )
365 {
366 SetError(22, "Try", tryScopes.back().GetSourceCodePos() );
367
368 EndTryCommand( true );
369 }
370}
371
[357]372void ThrowCommand( const char *Parameter )
373{
374 int backCp = cp;
375
376 char temporary[1024];
[361]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 }
[357]385 MakeMiddleCode( temporary );
386 ChangeOpcode( temporary );
387
388 cp = backCp;
[52]389}
390
[357]391void Opcode_Func_System_GetNowScopeCatchAddress()
392{
393 if( tryScopes.size() == 0 )
394 {
395 SetError(1,NULL,cp);
396 return;
397 }
[52]398
[357]399#ifdef _WIN64
400 //mov rax,catchAddress
[361]401 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::DataTable, true );
[357]402#else
403 //mov eax,catchAddress
[361]404 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::DataTable, true );
[357]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
[359]422void Opcode_Func_System_GetNowScopeFinallyAddress()
423{
424 if( tryScopes.size() == 0 )
425 {
426 SetError(1,NULL,cp);
427 return;
428 }
[357]429
[359]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
[52]454} // Exception
Note: See TracBrowser for help on using the repository browser.