source: dev/trunk/ab5.0/abdev/compiler_x64/Compile_CallProc.cpp @ 584

Last change on this file since 584 was 584, checked in by dai_9181, 15 years ago

[530][583]を64bit版にマージ。

File size: 17.2 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4
5#include "../BasicCompiler_Common/common.h"
6#include "Opcode.h"
7
8using namespace ActiveBasic::Compiler;
9
10void Call_DebugSys_SaveContext(){
11    //call _System_GetEip
12    extern const UserProc *pSub_System_GetEip;
13    compiler.codeGenerator.op_call(pSub_System_GetEip);
14
15    //mov rdx,rax
16    compiler.codeGenerator.op_mov_RR(REG_RDX,REG_RAX);
17
18    //mov rcx,rsp
19    compiler.codeGenerator.op_mov_RR(REG_RCX,REG_RSP);
20
21    //call _DebugSys_SaveContext
22    extern const UserProc *pSub_DebugSys_SaveContext;
23    compiler.codeGenerator.op_call(pSub_DebugSys_SaveContext);
24}
25
26bool Opcode_CallProcPtr( const char *variable, const char *lpszParms,ProcPointer *pProcPointer)
27{
28    extern BOOL bDebugSupportProc;
29    if( compiler.IsDebug() && bDebugSupportProc == 0 )
30    {
31        Call_DebugSys_SaveContext();
32    }
33
34
35    ////////////////////////
36    // パラメータのセット
37    ////////////////////////
38
39    //パラメータオブジェクトを生成
40    ParamImpl *pobj_parameter=0;
41    pobj_parameter=new ParamImpl(lpszParms);
42
43    // デフォルト引数を適用
44    pobj_parameter->ApplyDefaultParameters( pProcPointer->Params() );
45
46    //エラーチェック
47    if( !pobj_parameter->ErrorCheck(variable,pProcPointer->Params() ) ){
48        //パラメータにエラーがあるときは処理を終える
49        return false;
50    }
51
52    //スタックフレームに存在する既存のパラメータをバックアップ
53    pobj_parameter->BackupParameter( (int)pProcPointer->Params().size() );
54
55    //一時オブジェクトを生成
56    pobj_parameter->NewTempParameters( variable,pProcPointer->Params() );
57
58    //レジスタ、スタックフレームにセット
59    pobj_parameter->SetParameter(variable,pProcPointer->Params() );
60
61
62
63    RELATIVE_VAR RelativeVar;
64    GetVarOffsetReadOnly(variable,&RelativeVar,Type());
65    SetVarPtrToReg(REG_RAX,&RelativeVar);
66
67    //mov rax,qword ptr[rax]
68    compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_RAX,0,MOD_BASE);
69
70    //call rax
71    compiler.codeGenerator.PutOld(
72        (char)0xFF,
73        (char)0xD0
74    );
75
76
77    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
78    pobj_BlockReg->clear();
79
80    //一時オブジェクトを破棄
81    pobj_parameter->DeleteTempParameters();
82
83    //スタックフレームに存在する既存のパラメータを復元
84    pobj_parameter->RestoreParameter( (int)pProcPointer->Params().size() );
85
86    //パラメータオブジェクトを破棄
87    delete pobj_parameter;
88
89    return true;
90}
91
92bool Opcode_CallProc(const char *Parameter,const UserProc *pUserProc,DWORD dwFlags,const char *ObjectName)
93{
94    if( pUserProc->IsMacro() ){
95        if( lstrcmpi( pUserProc->GetName().c_str(), "Print" ) == 0 ){
96            Opcode_Print(Parameter,0);
97            return true;
98        }
99        if( lstrcmpi( pUserProc->GetName().c_str(), "Input" ) == 0 ){
100            Opcode_Input(Parameter);
101            return true;
102        }
103        if( lstrcmpi( pUserProc->GetName().c_str(), "Write" ) == 0 ){
104            Opcode_Print(Parameter,1);
105            return true;
106        }
107    }
108
109    pUserProc->Using();
110
111    bool isStatic = false;
112    const CClass *pobj_c = NULL;
113    const CMethod *pMethod = NULL;
114    Type leftType;
115    bool isFixedClass = false;
116    if( pUserProc->GetParentClassPtr() ){
117        //クラスのメンバ関数を呼び出す場合はアクセスチェックを行う
118        if(ObjectName[0] && (dwFlags&PROCFLAG_NEW)==0)
119        {
120            if(lstrcmpi(ObjectName,"Super")==0)
121            {
122                //クラスメンバ関数内から基底クラスの呼び出し
123                pobj_c=&compiler.GetCompilingClass().GetSuperClass();
124
125                isFixedClass = true;
126            }
127            else
128            {
129                //"->"によってオブジェクトを指定する通常のメンバ関数呼び出し
130                Type varType;
131                if( GetTermType( ObjectName, varType ) )
132                {
133                    if( varType.IsObject() )
134                    {
135                        pobj_c = &varType.GetClass();
136                        leftType = varType;
137                    }
138                }
139
140                if( !pobj_c )
141                {
142                    pobj_c = compiler.GetObjectModule().meta.FindClassSupportedTypeDef( ObjectName );
143                    if( pobj_c ){
144                        isStatic = true;
145                    }
146                    else{
147                        compiler.errorMessenger.Output(300,NULL,cp);
148                    }
149                }
150            }
151        }
152        else{
153            if(dwFlags&PROCFLAG_NEW){
154                GetVarType( ObjectName, leftType, false );
155
156                //New演算子によるコンストラクタ呼び出し
157                pobj_c = pUserProc->GetParentClassPtr();
158            }
159            else{
160                //クラスメンバ関数内から同一クラスのメンバ関数の呼び出し
161                pobj_c = &compiler.GetCompilingClass();
162            }
163        }
164
165
166        /////////////////////////////////
167        // メソッド情報を取得
168        /////////////////////////////////
169        pMethod = NULL;
170        if( ! isStatic ) pMethod = pobj_c->GetDynamicMethodOrInterfaceMethod( pUserProc );
171        if( ! pMethod ){
172            //動的メソッドが取得できなかったときは静的メソッドを当たる
173            pMethod = pobj_c->GetStaticMethods().GetMethodPtr( pUserProc );
174            if( !pMethod ){
175                compiler.errorMessenger.Output(300,NULL,cp);
176                return false;
177            }
178
179            //静的メンバ
180            isStatic = true;
181        }
182
183
184        //////////////////////////////
185        // アクセスエラーチェック
186        //////////////////////////////
187
188        if(ObjectName[0]){
189            //外部からの呼び出し
190            if( compiler.IsCompilingClass() && pobj_c == &compiler.GetCompilingClass() )
191            {
192                //同一クラスオブジェクトの場合はプライベートアクセスを容認する
193                if( pMethod->IsNoneAccess() )
194                {
195                    compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
196                    return false;
197                }
198            }
199            else
200            {
201                if( pMethod->IsPrivate()
202                    || pMethod->IsNoneAccess() )
203                {
204                    compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
205                    return false;
206                }
207                if( !pMethod->GetUserProc().GetParentClass().IsEqualsOrSubClass( pobj_c ) && pMethod->IsProtected() )
208                {
209                    compiler.errorMessenger.Output(110,pUserProc->GetName(),cp);
210                    return false;
211                }
212            }
213        }
214        else{
215            //クラス内部からの呼び出し(継承によるACCESS_NONのみをエラーとする)
216            if( pMethod->IsNoneAccess() ){
217                compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
218                return false;
219            }
220        }
221    }
222
223
224    ///////////////////////////////////////////////////////////////
225    // _System_LocalThisのダミーをセット
226    ///////////////////////////////////////////////////////////////
227
228    char temporary[VN_SIZE]={0};
229    if( pUserProc->GetParentClassPtr() && isStatic == false ){
230        //_System_LocalThis(第一パラメータ)のダミーを作成
231        lstrcpy(temporary,"0,");
232    }
233    if( pUserProc->ReturnType().IsStruct() ){
234        // ※ByRef _System_ReturnValue パラメータのダミーをセット
235        lstrcat(temporary,"0,");
236    }
237
238    if(Parameter[0]=='\0'&&temporary[0])
239        temporary[lstrlen(temporary)-1]=0;
240    else lstrcat(temporary,Parameter);
241
242
243    //パラメータセット前のspオフセットを取得(Newの場合はここにThisポインタが格納されている)
244    int this_sp_offset = pobj_sf->GetNowSp();
245
246
247    ////////////////////////
248    // パラメータをセット
249    ////////////////////////
250
251    //パラメータオブジェクトを生成
252    ParamImpl *pobj_parameter=0;
253    pobj_parameter=new ParamImpl(temporary);
254
255    // デフォルト引数を適用
256    pobj_parameter->ApplyDefaultParameters( pUserProc->RealParams() );
257
258    // 型パラメータを適用
259    pobj_parameter->SetLeftType( leftType );
260
261    //エラーチェック
262    if( !pobj_parameter->ErrorCheck(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetSecondParmNum() ) ){
263        //パラメータにエラーがあるときは処理を終える
264        return false;
265    }
266
267    if(pUserProc->IsMacro()){
268        //マクロ関数の場合は、パラメータ省略を考慮する
269        pobj_parameter->MacroParameterSupport( pUserProc->RealParams() );
270    }
271
272    //スタックフレームに存在する既存のパラメータをバックアップ
273    pobj_parameter->BackupParameter( (int)pUserProc->RealParams().size() );
274
275    //一時オブジェクトを生成
276    pobj_parameter->NewTempParameters( pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum() );
277
278    //レジスタ、スタックフレームにセット
279    pobj_parameter->SetParameter(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum(), pUserProc );
280
281    if( pUserProc->ReturnType().IsStruct() ){
282        //////////////////////////////////////////////////////
283        // 戻り値に構造体インスタンスを持つ場合
284        // ※ByRef _System_ReturnValue パラメータをセット
285        //////////////////////////////////////////////////////
286
287
288        //////////////////////////////////////////////////////
289        /////    レジスタ資源のバックアップ
290        {   BACKUP_REGISTER_RESOURCE
291        //////////////////////////////////////////////////////
292
293            int object_size = pUserProc->ReturnType().GetClass().GetSize();
294
295            //mov rcx,object_size
296            compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RCX,object_size);
297
298            //call calloc
299            extern const UserProc *pSub_calloc;
300            compiler.codeGenerator.op_call(pSub_calloc);
301
302            //mov r13,rax
303            compiler.codeGenerator.op_mov_RR(REG_R13,REG_RAX);
304
305        /////////////////////////////////////////////
306        //////   レジスタ資源を復元
307            RESTORE_REGISTER_RESOURCE
308        }////////////////////////////////////////////
309
310        if( pUserProc->GetParentClassPtr() && isStatic == false ){
311            //mov rdx,r13
312            compiler.codeGenerator.op_mov_RR(REG_RDX,REG_R13);
313        }
314        else{
315            //mov rcx,r13
316            compiler.codeGenerator.op_mov_RR(REG_RCX,REG_R13);
317        }
318    }
319
320
321    if( pUserProc->GetParentClassPtr() && isStatic == false ){
322        ///////////////////////////////
323        // メンバ関数の場合
324        // thisポインタをrcxで受け渡す
325        ///////////////////////////////
326
327        if(ObjectName[0] && (dwFlags&PROCFLAG_NEW)==0){
328            if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
329            else{
330                bool isLiteral, isNeedHeapFreeStructure = false;
331                Type baseType( DEF_OBJECT, *pUserProc->GetParentClassPtr() ) , resultType;
332                if( !TermOpe( ObjectName, baseType, resultType, isLiteral, isNeedHeapFreeStructure, NULL, false, !pMethod->IsConst() ) )
333                {
334                    return false;
335                }
336                if( !resultType.IsObject() )
337                {
338                    compiler.errorMessenger.OutputFatalError();
339                }
340
341                // 実態ポインタをraxにコピー
342                compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX );
343            }
344        }
345        else{
346InClassMember:
347            if(dwFlags&PROCFLAG_NEW){
348                //New演算子によるコンストラクタ呼び出しの場合
349
350                //mov rcx,qword ptr[rsp+offset]     ※スタックフレームを利用
351                pobj_sf->ref_offset_data(REG_RCX, this_sp_offset);
352            }
353            else{
354                //自身のオブジェクトのThisポインタをrcxにコピー
355                SetThisPtrToReg(REG_RCX);
356            }
357        }
358    }
359
360    if( pUserProc->IsVirtual() && !isFixedClass ){
361        int vtblIndex;
362        if( pobj_c->IsInterface() )
363        {
364            // インターフェイス メソッド呼び出し
365
366            int offset_vtbl = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__vtbl" );
367
368            // vtblのポインタを取得
369            //mov r11,qword ptr[rcx+offset_vtbl]
370            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,offset_vtbl,MOD_BASE_DISP8);
371
372            int offset_this = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__this" );
373
374            // インターフェイスの場合は更に__thisを取得する
375            //mov rcx,qword ptr[rcx+offset_this]
376            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,offset_this,MOD_BASE_DISP8);
377
378            int vtblMasterListIndex;
379            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
380            if( vtblMasterListIndex != 0 )
381            {
382                compiler.errorMessenger.OutputFatalError();
383            }
384        }
385        else if( pobj_c->IsComInterface() )
386        {
387            // COMインターフェイス メソッド呼び出し
388
389            //仮想関数(オブジェクトメソッド)呼び出し
390            // pObj -> vtbl1 -> func1
391            //               -> func2
392            //               -> func3
393
394            int vtblMasterListIndex;
395            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
396
397            // vtblのポインタを取得
398            //mov r11,qword ptr[rcx]
399            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE);        }
400        else
401        {
402            //仮想関数(オブジェクトメソッド)呼び出し
403            // pObj -> vtbl_master_list -> vtbl1 -> func1
404            //                                   -> func2
405            //                                   -> func3
406            //                          -> vtbl2 -> func1
407            //                                   -> func2
408            //                                   -> func3
409
410            int vtblMasterListIndex;
411            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
412
413            // vtblマスターリストのポインタを取得
414            //mov r11,qword ptr[rcx+sizeof(com_vtbl)]
415            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,PTR_SIZE,MOD_BASE_DISP8);
416
417            // vtblのポインタを取得
418            //mov r11,dword ptr[r11+vtblMasterListIndex]
419            compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_R11, REG_R11, vtblMasterListIndex*PTR_SIZE, MOD_BASE_DISP32 );
420        }
421
422        //call qword ptr[r11+func_index]
423        if( vtblIndex * PTR_SIZE <= 0x7F ){
424            compiler.codeGenerator.PutOld(
425                (char)0x41,
426                (char)0xFF,
427                (char)0x53,
428                (char)(vtblIndex*PTR_SIZE)
429            );
430        }
431        else{
432            compiler.codeGenerator.PutOld(
433                (char)0x41,
434                (char)0xFF,
435                (char)0x93,
436                (long)(vtblIndex*PTR_SIZE)
437            );
438        }
439    }
440    else{
441        //通常呼び出し
442
443        //call ProcAddr
444        compiler.codeGenerator.op_call(pUserProc);
445    }
446
447    /* 64コンパイラでは不要
448    if(pDllProc->bCdecl){
449        //add esp,ParmSize
450    }*/
451
452
453    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
454    pobj_BlockReg->clear();
455
456    //一時オブジェクトを破棄
457    pobj_parameter->DeleteTempParameters();
458
459    //スタックフレームに存在する既存のパラメータを復元
460    pobj_parameter->RestoreParameter( (int)pUserProc->RealParams().size() );
461
462    //パラメータオブジェクトを破棄
463    delete pobj_parameter;
464
465    return true;
466}
467
468bool Opcode_CallDllProc( const char *lpszParms, DllProc *pDllProc ){
469
470    extern BOOL bDebugSupportProc;
471    if( compiler.IsDebug() && bDebugSupportProc==0 && pDllProc->IsEqualSymbol( LexicalAnalyzer::FullNameToSymbol( "DebugBreak" ) ) )
472    {
473        Call_DebugSys_SaveContext();
474    }
475
476
477    ////////////////////////
478    // パラメータのセット
479    ////////////////////////
480
481    //パラメータオブジェクトを生成
482    ParamImpl *pobj_parameter=0;
483    pobj_parameter=new ParamImpl(lpszParms);
484
485    // デフォルト引数を適用
486    pobj_parameter->ApplyDefaultParameters( pDllProc->Params() );
487
488    //エラーチェック
489    if( !pobj_parameter->ErrorCheck( pDllProc->GetName(), pDllProc->Params() ) ){
490        //パラメータにエラーがあるときは処理を終える
491        return false;
492    }
493
494    //スタックフレームに存在する既存のパラメータをバックアップ
495    pobj_parameter->BackupParameter( (int)pDllProc->Params().size() );
496
497    //一時オブジェクトを生成
498    pobj_parameter->NewTempParameters( pDllProc->GetName(), pDllProc->Params() );
499
500    //レジスタ、スタックフレームにセット
501    pobj_parameter->SetParameter(pDllProc->GetName(), pDllProc->Params() );
502
503
504    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
505    pobj_BlockReg->clear();
506
507
508    //動的リンクされたプロシージャの呼び出し
509
510    //call dword ptr[ImportTable]
511    compiler.codeGenerator.op_call( pDllProc );
512
513    /* 64コンパイラでは不要
514    if(pDllProc->bCdecl){
515        //add esp,ParmSize
516    }*/
517
518    //一時オブジェクトを破棄
519    pobj_parameter->DeleteTempParameters();
520
521    //スタックフレームに存在する既存のパラメータを復元
522    pobj_parameter->RestoreParameter( (int)pDllProc->Params().size() );
523
524    //パラメータオブジェクトを破棄
525    delete pobj_parameter;
526
527    return true;
528}
529
530void Opcode_CallDelegate( const Delegate &dg, const char *methodPtrValueStr, const char *objPtrValueStr, const char *params )
531{
532    extern BOOL bDebugSupportProc;
533    if( compiler.IsDebug() && bDebugSupportProc == 0 )
534    {
535        Call_DebugSys_SaveContext();
536    }
537
538
539    ///////////////////////////////////////////////////////////////
540    // _System_LocalThisのダミーをセット
541    ///////////////////////////////////////////////////////////////
542
543    char temporary[VN_SIZE]={0};
544    bool isDynamicCall = false;
545    if( objPtrValueStr && objPtrValueStr[0] ){
546        //_System_LocalThis(第一パラメータ)のダミーを作成
547        lstrcpy(temporary,"0,");
548
549        isDynamicCall = true;
550    }
551    if( dg.ReturnType().IsStruct() ){
552        // ※ByRef _System_ReturnValue パラメータのダミーをセット
553        lstrcat(temporary,"0,");
554    }
555
556    if(params[0]=='\0'&&temporary[0])
557        temporary[lstrlen(temporary)-1]=0;
558    else lstrcat(temporary,params);
559
560    const Parameters *pParams = &dg.Params();
561    if( isDynamicCall )
562    {
563        pParams = &dg.GetDynamicParams();
564    }
565
566
567    ParamImpl *pobj_parameter = new ParamImpl( temporary );
568
569    //スタックフレームに存在する既存のパラメータをバックアップ
570    pobj_parameter->BackupParameter( (int)pParams->size() );
571
572    //一時オブジェクトを生成
573    pobj_parameter->NewTempParameters( dg.GetName(), *pParams );
574
575    //レジスタ、スタックフレームにセット
576    pobj_parameter->SetParameter( dg.GetName(), *pParams );
577
578
579    if( objPtrValueStr && objPtrValueStr[0] )
580    {
581        RELATIVE_VAR RelativeVar;
582        //Constアクセスが不可能なメソッドの場合
583        if( !GetVarOffsetReadWrite( objPtrValueStr, &RelativeVar, Type() ) ){
584            Jenga::Throw( "Opcode_CallDelegate関数内で呼ばれるGetVarOffsetReadWrite関数に失敗" );
585            return;
586        }
587
588        SetVarPtrToReg(REG_RCX,&RelativeVar);
589
590        // 参照を実体ポインタにする
591        //mov rcx,qword ptr[rcx]
592        compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE);
593    }
594
595
596    {
597        ////////////////////////
598        // call
599        ////////////////////////
600        RELATIVE_VAR RelativeVar;
601        GetVarOffsetReadOnly( methodPtrValueStr, &RelativeVar, Type() );
602        SetVarPtrToReg(REG_RAX,&RelativeVar);
603
604        //mov rax,qword ptr[rax]
605        compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_RAX,0,MOD_BASE);
606
607        //call rax
608        compiler.codeGenerator.PutOld(
609            (char)0xFF,
610            (char)0xD0
611        );
612    }
613
614
615    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
616    pobj_BlockReg->clear();
617
618    //一時オブジェクトを破棄
619    pobj_parameter->DeleteTempParameters();
620
621    //スタックフレームに存在する既存のパラメータを復元
622    pobj_parameter->RestoreParameter( (int)pParams->size() );
623
624    //パラメータオブジェクトを破棄
625    delete pobj_parameter;
626}
Note: See TracBrowser for help on using the repository browser.