source: dev/trunk/abdev/BasicCompiler64/Compile_Func.cpp@ 358

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

Try-Catchを試験的に実装。
(まだ下記の動作しか実装していません)
・Try
・Catch(パラメータ無し)
・Throw(パラメータ無し)

File size: 15.1 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4
5#include <Compiler.h>
6
7#include "../BasicCompiler_Common/common.h"
8#include "Opcode.h"
9
10int GetFunctionFromName(char *FuncName){
11 if( lstrcmpi( FuncName, "Len" ) == 0 ) return FUNC_LEN;
12 if( lstrcmpi( FuncName, "AddressOf" ) == 0 ) return FUNC_ADDRESSOF;
13 if( lstrcmpi( FuncName, "SizeOf" ) == 0 ) return FUNC_SIZEOF;
14 if( lstrcmpi( FuncName, "VarPtr" ) == 0 ) return FUNC_VARPTR;
15 if( lstrcmpi( FuncName, "ObjPtr" ) == 0 ) return FUNC_OBJPTR;
16 if( lstrcmpi( FuncName, "__delegate_dynamicmethod_call" ) == 0 ) return FUNC_DELEGATE_DYNAMICMETHOD_CALL;
17 if( lstrcmpi( FuncName, "__delegate_staticmethod_call" ) == 0 ) return FUNC_DELEGATE_STATICMETHOD_CALL;
18 if( lstrcmpi( FuncName, "_System_GetNowScopeCatchAddresses" ) == 0 )return FUNC_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS;
19 if( lstrcmpi( FuncName, "_System_GetBp" ) == 0 ) return FUNC_SYSTEM_GET_BP;
20 if( lstrcmpi( FuncName, "_System_GetSp" ) == 0 ) return FUNC_SYSTEM_GET_SP;
21 if( lstrcmpi( FuncName, "GetDouble" ) == 0 ) return FUNC_GETDOUBLE;
22 if( lstrcmpi( FuncName, "GetSingle" ) == 0 ) return FUNC_GETSINGLE;
23 if( lstrcmpi( FuncName, "GetQWord" ) == 0 ) return FUNC_GETQWORD;
24 if( lstrcmpi( FuncName, "GetDWord" ) == 0 ) return FUNC_GETDWORD;
25 if( lstrcmpi( FuncName, "GetWord" ) == 0 ) return FUNC_GETWORD;
26 if( lstrcmpi( FuncName, "GetByte" ) == 0 ) return FUNC_GETBYTE;
27 return 0;
28}
29void Opcode_Func_Len( const char *Parameter ){
30 BOOL bArrayHead;
31
32 const char *tempParm=Parameter;
33 char temporary[VN_SIZE];
34 char temp2[32];
35 Type type;
36 if( !GetVarType(Parameter,type,0) ){
37 sprintf(temporary,"_System_DummyStr2=%s",Parameter);
38 OpcodeCalc(temporary);
39
40 lstrcpy(temp2,"_System_DummyStr2");
41 tempParm=temp2;
42
43 type.SetType( DEF_OBJECT, compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr() );
44 }
45
46 if( type.IsStringClass() ){
47 //Stringオブジェクトの場合
48 sprintf(temporary,"%s.Length",tempParm);
49
50 int reg=REG_RAX;
51 NumOpe(&reg,temporary,Type(),Type());
52 return;
53 }
54
55 Subscripts subscripts;
56 RELATIVE_VAR RelativeVar;
57 if(!GetVarOffsetReadOnly(tempParm,&RelativeVar,type,&subscripts)) return;
58
59 if(type.GetBasicType()&FLAG_PTR){
60 type.SetBasicType( type.GetBasicType() & ( ~FLAG_PTR ) );
61
62 bArrayHead=1;
63 }
64 else bArrayHead=0;
65
66 int typeSize = type.GetSize();
67
68 if(bArrayHead) typeSize*=JumpSubScripts(subscripts);
69
70 //mov rax,TypeSize
71 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,typeSize);
72
73 return;
74}
75
76void _Opcode_Func_AddressOf( const char *methodInstanceName, const UserProc &userProc )
77{
78 if( userProc.IsVirtual() )
79 {
80 ///////////////////////////////
81 // 仮想関数の場合
82 // thisポインタをrcxにコピー
83 ///////////////////////////////
84
85 const CClass *pobj_c;
86
87 char ObjectName[VN_SIZE];
88 ReferenceKind referenceKind;
89 SplitObjectName(methodInstanceName,ObjectName, referenceKind );
90
91 if(ObjectName[0]){
92 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
93 else{
94 RELATIVE_VAR RelativeVar;
95 Type type;
96 if(!GetVarOffsetReadOnly(ObjectName,&RelativeVar,type)) return;
97 SetVarPtrToReg(REG_RCX,&RelativeVar);
98
99 //参照タイプが整合しているかをチェック
100 if( !( type.IsObject() && referenceKind == RefDot
101 || type.IsObjectPtr() && referenceKind == RefPointer ) )
102 {
103 SetError(104,ObjectName,cp);
104 }
105
106 if(type.IsObjectPtr()){
107 //mov rcx,qword ptr[rcx]
108 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE);
109 }
110 }
111 }
112 else{
113InClassMember:
114 //自身のオブジェクトのThisポインタをrcxにコピー
115 SetThisPtrToReg(REG_RCX);
116
117 pobj_c=compiler.pCompilingClass;
118 }
119
120
121 int vtblIndex;
122 if( pobj_c->IsInterface() )
123 {
124 // インターフェイスメソッド
125
126 int offset_vtbl = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__vtbl" );
127
128 // vtblのポインタを取得
129 //mov r11,qword ptr[rcx+offset_vtbl]
130 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,offset_vtbl,MOD_BASE_DISP8);
131
132 int offset_this = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__this" );
133
134 // インターフェイスの場合は更に__thisを取得する
135 //mov rcx,qword ptr[rcx+offset_this]
136 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,offset_this,MOD_BASE_DISP8);
137
138 int vtblMasterListIndex;
139 pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex );
140 if( vtblMasterListIndex != 0 )
141 {
142 SetError();
143 }
144 }
145 else
146 {
147 //仮想関数(オブジェクトメソッド)
148 // pObj -> vtbl_master_list -> vtbl1 -> func1
149 // -> func2
150 // -> func3
151 // -> vtbl2 -> func1
152 // -> func2
153 // -> func3
154
155 int vtblMasterListIndex;
156 pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex );
157
158 // vtblマスターリストのポインタを取得
159 //mov r11,qword ptr[rcx]
160 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE);
161
162 // vtblのポインタを取得
163 //mov r11,dword ptr[r11+vtblMasterListIndex]
164 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_R11, REG_R11, vtblMasterListIndex, MOD_BASE_DISP32 );
165 }
166
167 //mov rax,qword ptr[r11+func_index]
168 if( vtblIndex * PTR_SIZE <= 0x7F )
169 {
170 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP8);
171 }
172 else
173 {
174 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP32);
175 }
176 }
177 else{
178 //一般の関数
179
180 //mov rax,ProcAddr
181 compiler.codeGenerator.op_addressof( REG_RAX, &userProc );
182 }
183
184 userProc.Using();
185}
186void Opcode_CreateDelegate( const CClass &dgClass, const char *methodInstanceName, const UserProc &userProc )
187{
188 /////////////////////////////////////////////////////////////////
189 // 関数ポインタをpush
190 /////////////////////////////////////////////////////////////////
191
192 //mov rax,AddressOf
193 _Opcode_Func_AddressOf( methodInstanceName, userProc );
194
195
196 if( userProc.GetMethod().IsDynamic() )
197 {
198 //mov rdx,rax
199 compiler.codeGenerator.op_mov_RR( REG_RDX, REG_RAX );
200
201 pobj_BlockReg->lock( REG_RDX );
202
203
204 /////////////////////////////////////////////////////////////////
205 // オブジェクト ポインタをpush
206 /////////////////////////////////////////////////////////////////
207
208 // オブジェクト名を取得
209 char objectName[VN_SIZE];
210 char memberName[VN_SIZE];
211 char *thisPtrName = "This";
212 Type type;
213 if( SplitMemberName( methodInstanceName, objectName, memberName ) )
214 {
215 if( GetVarType( objectName, type, false ) )
216 {
217 thisPtrName = objectName;
218 }
219 }
220
221 // オブジェクト ポインタを取得
222 RELATIVE_VAR relativeVar;
223 GetVarOffsetReadOnly( thisPtrName, &relativeVar, type );
224 if( !type.IsObject() )
225 {
226 extern int cp;
227 SetError(1,NULL,cp);
228 return;
229 }
230
231 SetVarPtrToReg( REG_RAX, &relativeVar );
232
233 //mov rcx,dword ptr[rax]
234 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RCX, REG_RAX, 0, MOD_BASE );
235
236 pobj_BlockReg->unlock( REG_RDX );
237 }
238 else
239 {
240 //mov rcx,rax
241 compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX );
242 }
243
244
245 /////////////////////////////////////////////////////////////////
246 // call _CreateDynamicDelegate/_CreateStaticDelegate
247 /////////////////////////////////////////////////////////////////
248
249 std::vector<const UserProc *> subs;
250 if( userProc.GetMethod().IsDynamic() )
251 {
252 dgClass.GetStaticMethods().Enum( "_CreateDynamicDelegate", subs );
253 }
254 else
255 {
256 dgClass.GetStaticMethods().Enum( "_CreateStaticDelegate", subs );
257 }
258
259 // call _CreateDynamicDelegate
260 compiler.codeGenerator.op_call( subs[0] );
261}
262void Opcode_Func_AddressOf( const char *name, const Type &baseType, bool isCallOn, Type &resultType )
263{
264 extern int cp;
265 const UserProc *pUserProc;
266
267 const Parameters *pBaseParams = NULL;
268 if( baseType.IsProcPtr() )
269 {
270 // 左辺で関数ポインタを要求されているとき
271 pBaseParams = &compiler.GetObjectModule().meta.GetProcPointers()[baseType.GetIndex()]->Params();
272 }
273 else if( baseType.IsDelegate() )
274 {
275 // 左辺でデリゲートを要求されているとき
276 pBaseParams = &baseType.GetClass().GetDelegate().Params();
277 }
278
279 if( pBaseParams )
280 {
281 //左辺の型にのっとり、オーバーロードを解決
282
283 std::vector<const UserProc *> subs;
284 GetOverloadSubHash( name, subs );
285 if( subs.size() == 0 ){
286 SetError(27,name,cp);
287 return;
288 }
289
290 //オーバーロードを解決
291 pUserProc=OverloadSolution( name, subs, *pBaseParams, Type() );
292
293 if( isCallOn && baseType.IsDelegate() )
294 {
295 // コード生成を伴う場合はエラーチェックを行う
296 if( !pUserProc->Params().Equals( *pBaseParams )
297 || !pUserProc->ReturnType().Equals( baseType.GetClass().GetDelegate().ReturnType() ) )
298 {
299 if( baseType.IsDelegate() )
300 {
301 SetError(67, name, cp );
302 }
303 else
304 {
305 SetError(66, name, cp );
306 }
307 }
308 }
309
310 if(!pUserProc){
311 SetError(27,name,cp);
312 return;
313 }
314 }
315 else{
316 pUserProc=GetSubHash(name);
317 if(!pUserProc){
318 SetError(27,name,cp);
319 return;
320 }
321 }
322
323 if( baseType.IsDelegate() )
324 {
325 if( isCallOn )
326 {
327 // デリゲートのとき
328 Opcode_CreateDelegate( baseType.GetClass(), name, *pUserProc );
329 }
330 resultType = baseType;
331 }
332 else
333 {
334 if( isCallOn )
335 {
336 // 関数ポインタのとき
337 _Opcode_Func_AddressOf( name, *pUserProc );
338 }
339 resultType.SetBasicType( DEF_PTR_VOID );
340 }
341}
342void Opcode_Func_SizeOf( const string &typeName ){
343 Type tempType;
344 if( !compiler.StringToType( typeName, tempType ) ){
345 SetError(3,typeName,cp);
346 return;
347 }
348
349 int typeSize = ( tempType.IsObject() ) ?
350 tempType.GetClass().GetSize() : tempType.GetSize();
351
352 //mov rax,size
353 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,typeSize);
354}
355void Opcode_Func_VarPtr( const char *Parameter, Type &resultType, bool isCallOn ){
356 if( isCallOn == false ){
357 // 戻り値の型を取得するだけ
358
359 //変数のアドレスを取得
360 if(!GetVarType( Parameter, resultType, true )) return;
361
362 resultType.PtrLevelUp();
363
364 return;
365 }
366
367 RELATIVE_VAR RelativeVar;
368
369 //変数のアドレスを取得
370 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
371
372 int beforeType = resultType.GetBasicType();
373
374 resultType.PtrLevelUp();
375
376 SetVarPtrToReg(REG_RAX,&RelativeVar);
377
378 // TODO: 取り除く(この動きはObjPtrに託す)
379 /*
380 if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){
381 //参照をオブジェクトポインタに変更
382
383 //mov rax,qword ptr[rax]
384 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE );
385
386 SetError(-120,NULL,cp);
387 }*/
388}
389void Opcode_Func_ObjPtr( const char *Parameter, Type &resultType, bool isCallOn ){
390 if( isCallOn == false ){
391 // 戻り値の型を取得するだけ
392
393 //変数のアドレスを取得
394 if(!GetVarType( Parameter, resultType, true )) return;
395
396 resultType.PtrLevelUp();
397
398 return;
399 }
400
401 RELATIVE_VAR RelativeVar;
402
403 //変数のアドレスを取得
404 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
405
406 int beforeType = resultType.GetBasicType();
407
408 resultType.PtrLevelUp();
409
410 SetVarPtrToReg(REG_RAX,&RelativeVar);
411
412 if( lstrcmpi( Parameter, "This" )==0 ){
413 // Thisの場合は特別にオブジェクトポインタが返ってくるので、何もせずに抜ける
414 }
415 else if( beforeType == DEF_OBJECT ){
416 //参照をオブジェクトポインタに変更
417
418 //mov rax,qword ptr[rax]
419 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE );
420 }
421 else{
422 SetError(134,NULL,cp );
423 }
424}
425
426void Opcode_Func_delegate_call( const char *paramsStr, Type &resultType, bool isDynamicCall, bool isCallOn )
427{
428 if( isCallOn )
429 {
430 int i = 0;
431 char methodPtrParamStr[VN_SIZE];
432 i = GetOneParameter( paramsStr, i, methodPtrParamStr );
433
434 char objPtrValueStr[VN_SIZE] = "";
435 if( isDynamicCall )
436 {
437 i = GetOneParameter( paramsStr, i, objPtrValueStr );
438 }
439
440 Opcode_CallDelegate( compiler.pCompilingClass->GetDelegate(), methodPtrParamStr, objPtrValueStr, paramsStr + i );
441 }
442
443 resultType = UserProc::CompilingUserProc().ReturnType();
444}
445
446void Opcode_Func_System_Get_Bp()
447{
448 //mov rax,rbp
449 compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RBP);
450}
451void Opcode_Func_System_Get_Sp()
452{
453 //mov rax,rsp
454 compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RSP);
455}
456
457void Opcode_Func_GetPtrData( const char *Parameter, const int type ){
458 int reg=REG_RAX;
459 Type tempType;
460 if( !NumOpe(&reg,Parameter,Type(),tempType) ){
461 return;
462 }
463 if(!tempType.IsWhole()){
464 SetError(11,Parameter,cp);
465 return;
466 }
467
468 if(type==DEF_DOUBLE){
469 //movlpd xmm0,qword ptr[rax]
470 compiler.codeGenerator.op_movlpd_RM(REG_XMM0,REG_RAX,0,MOD_BASE);
471 }
472 else if(type==DEF_SINGLE){
473 //movss xmm0,dword ptr[rax]
474 compiler.codeGenerator.op_movss_RM(REG_XMM0,REG_RAX,0,MOD_BASE);
475 }
476 else{
477 //mov rax,ptr[rax]
478 compiler.codeGenerator.op_mov_RM(Type(type).GetSize(),REG_RAX,REG_RAX,0,MOD_BASE);
479 }
480}
481
482bool Opcode_CallFunc( const char *Parameter, const int FuncNum, const Type &baseType, Type &resultType, bool isCallOn )
483{
484 switch(FuncNum){
485 case FUNC_LEN:
486 if( isCallOn ) Opcode_Func_Len(Parameter);
487 resultType.SetBasicType( DEF_LONG );
488 break;
489 case FUNC_ADDRESSOF:
490 Opcode_Func_AddressOf( Parameter, baseType, isCallOn, resultType );
491 break;
492 case FUNC_SIZEOF:
493 if( isCallOn ) Opcode_Func_SizeOf(Parameter);
494 resultType.SetBasicType( DEF_LONG );
495 break;
496 case FUNC_VARPTR:
497 Opcode_Func_VarPtr( Parameter, resultType, isCallOn );
498 break;
499 case FUNC_OBJPTR:
500 Opcode_Func_ObjPtr( Parameter, resultType, isCallOn );
501 break;
502 case FUNC_DELEGATE_DYNAMICMETHOD_CALL:
503 Opcode_Func_delegate_call( Parameter, resultType, true, isCallOn );
504 break;
505 case FUNC_DELEGATE_STATICMETHOD_CALL:
506 Opcode_Func_delegate_call( Parameter, resultType, false, isCallOn );
507 break;
508 case FUNC_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS:
509 if( isCallOn ) Exception::Opcode_Func_System_GetNowScopeCatchAddress();
510 resultType.SetBasicType( DEF_PTR_VOID );
511 break;
512 case FUNC_SYSTEM_GET_BP:
513 if( isCallOn ) Opcode_Func_System_Get_Bp();
514 resultType.SetBasicType( DEF_INT64 );
515 break;
516 case FUNC_SYSTEM_GET_SP:
517 if( isCallOn ) Opcode_Func_System_Get_Sp();
518 resultType.SetBasicType( DEF_INT64 );
519 break;
520
521 case FUNC_GETDOUBLE:
522 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DOUBLE);
523 resultType.SetBasicType( DEF_DOUBLE );
524 break;
525 case FUNC_GETSINGLE:
526 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_SINGLE);
527 resultType.SetBasicType( DEF_SINGLE );
528 break;
529 case FUNC_GETQWORD:
530 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_QWORD);
531 resultType.SetBasicType( DEF_QWORD );
532 break;
533 case FUNC_GETDWORD:
534 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DWORD);
535 resultType.SetBasicType( DEF_DWORD );
536 break;
537 case FUNC_GETWORD:
538 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_WORD);
539 resultType.SetBasicType( DEF_WORD );
540 break;
541 case FUNC_GETBYTE:
542 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_BYTE);
543 resultType.SetBasicType( DEF_BYTE );
544 break;
545 default:
546 return false;
547 }
548 return true;
549}
Note: See TracBrowser for help on using the repository browser.