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

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

COM修飾子に対応。COMインターフェイスを呼び出せるようにした

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