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

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

32ビットコンパイラでグローバル領域のTryスコープが正常にコンパイルできないバグを修正。
Catch、Finally節を持たないTryスコープを警告の対象とした。

File size: 10.3 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 {
175 Finally();
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 {
279 SetError(73,NULL,cp);
280 }
281 }
282 }
283
[361]284 tryScopes.back().Catch( paramType );
[364]285
286 if( paramType.IsObject() )
287 {
288 int backCp = cp;
289
290 char temporary[1024];
291 sprintf( temporary, "Dim %s = Thread.CurrentThread().__GetThrowintParamObject() As %s", varName, paramType.GetClass().GetFullName().c_str() );
292 MakeMiddleCode( temporary );
293 ChangeOpcode( temporary );
294 lstrcpy( temporary, "Thread.CurrentThread().__Catched()" );
295 MakeMiddleCode( temporary );
296 ChangeOpcode( temporary );
297
298 cp = backCp;
299 }
[52]300}
[357]301void FinallyCommand()
302{
[359]303 tryScopes.back().Finally();
304
305 int backCp = cp;
306
307 char temporary[1024];
308 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->FinishFinally()" );
309 MakeMiddleCode( temporary );
310 ChangeOpcode( temporary );
311
312 cp = backCp;
313
314 //Tryスコープに入るときに引き渡されるパラメータ値を解決
315 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForFinallyAddress(), compiler.codeGenerator.GetNativeCodeSize() );
[52]316}
[357]317void EndTryCommand()
318{
319 if( tryScopes.size() == 0 )
320 {
321 SetError(1,NULL,cp);
322 return;
323 }
324
[365]325 if( !tryScopes.back().IsDefinedFinally() && !tryScopes.back().IsCatched() )
326 {
327 // CatchもFinallyも存在しないとき
328 SetError(-108,NULL,tryScopes.back().GetSourceCodePos() );
329 }
330
[361]331 int dataTableOffset = tryScopes.back().GenerateCatchTable();
[357]332
[361]333 // _System_GetNowScopeCatchAddressesを解決
334 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForCatchAddress(), dataTableOffset );
[359]335
336 if( !tryScopes.back().IsDefinedFinally() )
337 {
338 // Finallyが定義されていないときは空のFinallyを定義しておく
339 FinallyCommand();
340 }
341
[361]342 int backCp = cp;
343
[357]344 char temporary[1024];
345 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
346 MakeMiddleCode( temporary );
347 ChangeOpcode( temporary );
348
349 cp = backCp;
350
[359]351 tryScopes.back().EndTry();
[357]352 tryScopes.pop_back();
[52]353}
354
[357]355void ThrowCommand( const char *Parameter )
356{
357 int backCp = cp;
358
359 char temporary[1024];
[361]360 if( Parameter[0] )
361 {
362 sprintf( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowWithParam(%s)", Parameter );
363 }
364 else
365 {
366 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowNoneParam()" );
367 }
[357]368 MakeMiddleCode( temporary );
369 ChangeOpcode( temporary );
370
371 cp = backCp;
[52]372}
373
[357]374void Opcode_Func_System_GetNowScopeCatchAddress()
375{
376 if( tryScopes.size() == 0 )
377 {
378 SetError(1,NULL,cp);
379 return;
380 }
[52]381
[357]382#ifdef _WIN64
383 //mov rax,catchAddress
[361]384 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::DataTable, true );
[357]385#else
386 //mov eax,catchAddress
[361]387 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::DataTable, true );
[357]388#endif
389
390 tryScopes.back().RegistPertialScheduleForCatchAddress( pPertialSchedule );
391
392 /*
393 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
394
395#ifdef _WIN64
396 //mov rax,dataTableOffset
397 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
398#else
399 //mov eax,dataTableOffset
400 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
401#endif
402 */
403}
404
[359]405void Opcode_Func_System_GetNowScopeFinallyAddress()
406{
407 if( tryScopes.size() == 0 )
408 {
409 SetError(1,NULL,cp);
410 return;
411 }
[357]412
[359]413#ifdef _WIN64
414 //mov rax,finallyAddress
415 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::CatchAddress, true );
416#else
417 //mov eax,finallyAddress
418 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::CatchAddress, true );
419#endif
420
421 tryScopes.back().RegistPertialScheduleForFinallyAddress( pPertialSchedule );
422
423 /*
424 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
425
426#ifdef _WIN64
427 //mov rax,dataTableOffset
428 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
429#else
430 //mov eax,dataTableOffset
431 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
432#endif
433 */
434}
435
436
[52]437} // Exception
Note: See TracBrowser for help on using the repository browser.