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

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

Catchのオーバーロードを実装中

File size: 8.4 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 bool isDefinedFinally;
41
42 CatchScopes catchScopes;
43
44 std::vector<const PertialSchedule *> finallySchedules;
45 void JmpFinally()
46 {
47 finallySchedules.push_back(
48 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
49 );
50 }
51 void ResolveJmpFinally()
52 {
53 BOOST_FOREACH( const PertialSchedule *pPertialSchedule, finallySchedules )
54 {
55 compiler.codeGenerator.opfix_JmpPertialSchedule( pPertialSchedule );
56 }
57 }
58
59 const PertialSchedule *pPertialScheduleForCatchAddress;
60 const PertialSchedule *pPertialScheduleForFinallyAddress;
61
62public:
63 TryScope()
64 : isDefinedFinally( false )
65 {
66 }
67 ~TryScope()
68 {
69 }
70
71 const CatchScopes &GetCatchScopes() const
72 {
73 return catchScopes;
74 }
75 bool IsCatched() const
76 {
77 return ( catchScopes.size() != 0 );
78 }
79 bool IsDefinedFinally() const
80 {
81 return isDefinedFinally;
82 }
83
84 void RegistPertialScheduleForCatchAddress( const PertialSchedule *pPertialScheduleForCatchAddress )
85 {
86 this->pPertialScheduleForCatchAddress = pPertialScheduleForCatchAddress;
87 }
88 const PertialSchedule *GetPertialScheduleForCatchAddress() const
89 {
90 return pPertialScheduleForCatchAddress;
91 }
92 void RegistPertialScheduleForFinallyAddress( const PertialSchedule *pPertialScheduleForFinallyAddress )
93 {
94 this->pPertialScheduleForFinallyAddress = pPertialScheduleForFinallyAddress;
95 }
96 const PertialSchedule *GetPertialScheduleForFinallyAddress() const
97 {
98 return pPertialScheduleForFinallyAddress;
99 }
100
101
102
103 void Try()
104 {
105 }
106
107 void Catch( Type &paramType )
108 {
109 if( isDefinedFinally )
110 {
111 SetError(71,NULL,cp);
112 return;
113 }
114
115 JmpFinally();
116
117 catchScopes.push_back( CatchScope( paramType, compiler.codeGenerator.GetNativeCodeSize() ) );
118 }
119 void Finally()
120 {
121 if( isDefinedFinally )
122 {
123 SetError(70,NULL,cp);
124 return;
125 }
126
127 isDefinedFinally = true;
128
129 ResolveJmpFinally();
130 }
131
132 void EndTry()
133 {
134 if( !isDefinedFinally )
135 {
136 Finally();
137 }
138 }
139
140 int GenerateCatchTable()
141 {
142 int size = static_cast<int>(( (catchScopes.size()+1)*2 ) * sizeof(LONG_PTR));
143 BYTE *buffer = (BYTE *)calloc( size, 1 );
144
145 int pos = 0;
146 BOOST_FOREACH( const CatchScope &catchScope, catchScopes )
147 {
148 // パラメータのクラス名
149 char paramName[VN_SIZE] = "";
150 int paramNameDataTableOffset = 0;
151 if( catchScope.GetParamType().IsObject() )
152 {
153 lstrcpy( paramName, catchScope.GetParamType().GetClass().GetFullName().c_str() );
154 }
155 paramNameDataTableOffset = compiler.GetObjectModule().dataTable.AddString( paramName );
156 *((LONG_PTR *)(buffer+pos)) = paramNameDataTableOffset;
157 pos += sizeof(LONG_PTR);
158
159 // Catchアドレス
160 *((LONG_PTR *)(buffer+pos)) = catchScope.GetCodePos();
161 pos += sizeof(LONG_PTR);
162 }
163
164 int dataTableOffset = compiler.GetObjectModule().dataTable.AddBinary( buffer, size );
165
166 free( buffer );
167
168 pos = 0;
169 BOOST_FOREACH( const CatchScope &catchScope, catchScopes )
170 {
171 // パラメータのクラス名
172 compiler.GetObjectModule().dataTable.schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + pos ) );
173 pos += sizeof(LONG_PTR);
174
175 // Catchアドレス
176 compiler.GetObjectModule().dataTable.schedules.push_back( Schedule( &UserProc::CompilingUserProc(), dataTableOffset + pos ) );
177 compiler.GetObjectModule().dataTable.schedules.back().SpecifyCatchAddress();
178 pos += sizeof(LONG_PTR);
179 }
180
181 return dataTableOffset;
182 }
183};
184typedef std::vector<TryScope> TryScopes;
185
186TryScopes tryScopes;
187
188void TryCommand()
189{
190 if( UserProc::IsGlobalAreaCompiling() )
191 {
192 SetError();
193 }
194
195 tryScopes.push_back( TryScope() );
196 tryScopes.back().Try();
197
198 int backCp = cp;
199
200 char temporary[1024];
201 lstrcpy( temporary, "ExceptionService.BeginTryScope( _System_GetNowScopeCatchAddresses() As VoidPtr, _System_GetNowScopeFinallyAddresses() As VoidPtr, _System_GetBp() As LONG_PTR, _System_GetSp() As LONG_PTR )" );
202 MakeMiddleCode( temporary );
203 ChangeOpcode( temporary );
204
205 cp = backCp;
206}
207void CatchCommand( const char *parameter )
208{
209 if( tryScopes.size() == 0 )
210 {
211 SetError(1,NULL,cp);
212 return;
213 }
214
215 Type paramType;
216 if( parameter[0] )
217 {
218 char varName[VN_SIZE], typeName[VN_SIZE];
219 SplitSyntacticForAs( parameter, varName, typeName );
220 if( !typeName[0] )
221 {
222 SetError(72,NULL,cp);
223 }
224 else
225 {
226 if( !compiler.StringToType( typeName, paramType ) )
227 {
228 SetError(73,NULL,cp);
229 }
230 }
231 }
232
233 tryScopes.back().Catch( paramType );
234}
235void FinallyCommand()
236{
237 tryScopes.back().Finally();
238
239 int backCp = cp;
240
241 char temporary[1024];
242 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->FinishFinally()" );
243 MakeMiddleCode( temporary );
244 ChangeOpcode( temporary );
245
246 cp = backCp;
247
248 //Tryスコープに入るときに引き渡されるパラメータ値を解決
249 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForFinallyAddress(), compiler.codeGenerator.GetNativeCodeSize() );
250}
251void EndTryCommand()
252{
253 if( tryScopes.size() == 0 )
254 {
255 SetError(1,NULL,cp);
256 return;
257 }
258
259 int dataTableOffset = tryScopes.back().GenerateCatchTable();
260
261 // _System_GetNowScopeCatchAddressesを解決
262 compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForCatchAddress(), dataTableOffset );
263
264 if( !tryScopes.back().IsDefinedFinally() )
265 {
266 // Finallyが定義されていないときは空のFinallyを定義しておく
267 FinallyCommand();
268 }
269
270 int backCp = cp;
271
272 char temporary[1024];
273 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
274 MakeMiddleCode( temporary );
275 ChangeOpcode( temporary );
276
277 cp = backCp;
278
279 tryScopes.back().EndTry();
280 tryScopes.pop_back();
281}
282
283void ThrowCommand( const char *Parameter )
284{
285 int backCp = cp;
286
287 char temporary[1024];
288 if( Parameter[0] )
289 {
290 sprintf( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowWithParam(%s)", Parameter );
291 }
292 else
293 {
294 lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->_ThrowNoneParam()" );
295 }
296 MakeMiddleCode( temporary );
297 ChangeOpcode( temporary );
298
299 cp = backCp;
300}
301
302void Opcode_Func_System_GetNowScopeCatchAddress()
303{
304 if( tryScopes.size() == 0 )
305 {
306 SetError(1,NULL,cp);
307 return;
308 }
309
310#ifdef _WIN64
311 //mov rax,catchAddress
312 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::DataTable, true );
313#else
314 //mov eax,catchAddress
315 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::DataTable, true );
316#endif
317
318 tryScopes.back().RegistPertialScheduleForCatchAddress( pPertialSchedule );
319
320 /*
321 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
322
323#ifdef _WIN64
324 //mov rax,dataTableOffset
325 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
326#else
327 //mov eax,dataTableOffset
328 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
329#endif
330 */
331}
332
333void Opcode_Func_System_GetNowScopeFinallyAddress()
334{
335 if( tryScopes.size() == 0 )
336 {
337 SetError(1,NULL,cp);
338 return;
339 }
340
341#ifdef _WIN64
342 //mov rax,finallyAddress
343 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::CatchAddress, true );
344#else
345 //mov eax,finallyAddress
346 const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::CatchAddress, true );
347#endif
348
349 tryScopes.back().RegistPertialScheduleForFinallyAddress( pPertialSchedule );
350
351 /*
352 int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
353
354#ifdef _WIN64
355 //mov rax,dataTableOffset
356 compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
357#else
358 //mov eax,dataTableOffset
359 compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
360#endif
361 */
362}
363
364
365} // Exception
Note: See TracBrowser for help on using the repository browser.