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

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

[426]を64bit版にマージ。

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