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

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

DataTable::AddWStringメソッドを追加。

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