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

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

Tryスコープのコード補完機能のバグを修正(EndTryコード補間が過剰に行われていた)。
コンパイラのログ生成処理をきった。

File size: 10.5 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 Finally();
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(73,NULL,cp);
280 }
281 }
282 }
283
284 tryScopes.back().Catch( paramType );
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 }
300}
301void FinallyCommand()
302{
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() );
316}
317void EndTryCommand( bool isNoWarning )
318{
319 if( tryScopes.size() == 0 )
320 {
321 SetError(12,"End Try",cp);
322 return;
323 }
324
325 if( !isNoWarning && !tryScopes.back().IsDefinedFinally() && !tryScopes.back().IsCatched() )
326 {
327 // CatchもFinallyも存在しないとき
328 SetError(-108,NULL,tryScopes.back().GetSourceCodePos() );
329 }
330
331 int dataTableOffset = tryScopes.back().GenerateCatchTable();
332
333 // _System_GetNowScopeCatchAddressesを解決
334 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForCatchAddress(), dataTableOffset );
335
336 if( !tryScopes.back().IsDefinedFinally() )
337 {
338 // Finallyが定義されていないときは空のFinallyを定義しておく
339 FinallyCommand();
340 }
341
342 int backCp = cp;
343
344 char temporary[1024];
345 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
346 MakeMiddleCode( temporary );
347 ChangeOpcode( temporary );
348
349 cp = backCp;
350
351 tryScopes.back().EndTry();
352 tryScopes.pop_back();
353}
354
355void InspectTryScope()
356{
357 while( tryScopes.size() > 0 )
358 {
359 SetError(22, "Try", tryScopes.back().GetSourceCodePos() );
360
361 EndTryCommand( true );
362 }
363}
364
365void ThrowCommand( const char *Parameter )
366{
367 int backCp = cp;
368
369 char temporary[1024];
370 if( Parameter[0] )
371 {
372 sprintf( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowWithParam(%s)", Parameter );
373 }
374 else
375 {
376 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowNoneParam()" );
377 }
378 MakeMiddleCode( temporary );
379 ChangeOpcode( temporary );
380
381 cp = backCp;
382}
383
384void Opcode_Func_System_GetNowScopeCatchAddress()
385{
386 if( tryScopes.size() == 0 )
387 {
388 SetError(1,NULL,cp);
389 return;
390 }
391
392#ifdef _WIN64
393 //mov rax,catchAddress
394 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::DataTable, true );
395#else
396 //mov eax,catchAddress
397 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::DataTable, true );
398#endif
399
400 tryScopes.back().RegistPertialScheduleForCatchAddress( pPertialSchedule );
401
402 /*
403 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
404
405#ifdef _WIN64
406 //mov rax,dataTableOffset
407 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
408#else
409 //mov eax,dataTableOffset
410 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
411#endif
412 */
413}
414
415void Opcode_Func_System_GetNowScopeFinallyAddress()
416{
417 if( tryScopes.size() == 0 )
418 {
419 SetError(1,NULL,cp);
420 return;
421 }
422
423#ifdef _WIN64
424 //mov rax,finallyAddress
425 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::CatchAddress, true );
426#else
427 //mov eax,finallyAddress
428 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::CatchAddress, true );
429#endif
430
431 tryScopes.back().RegistPertialScheduleForFinallyAddress( pPertialSchedule );
432
433 /*
434 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
435
436#ifdef _WIN64
437 //mov rax,dataTableOffset
438 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
439#else
440 //mov eax,dataTableOffset
441 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
442#endif
443 */
444}
445
446
447} // Exception
Note: See TracBrowser for help on using the repository browser.