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

Last change on this file since 587 was 587, checked in by dai_9181, 16 years ago

[585][586]をリバース。NativeCodeクラスとMetaクラスは依存関係があるので分離しない方針とする。

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