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

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

[505][513]を64bit版にマージ。

File size: 17.1 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.pCompilingClass->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.GetClasses().Find(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.pCompilingClass;
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(pobj_c==compiler.pCompilingClass){
191                //同一クラスオブジェクトの場合はプライベートアクセスを容認する
192                if( pMethod->IsNoneAccess() ){
193                    compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
194                    return false;
195                }
196            }
197            else{
198                if( pMethod->IsPrivate()
199                    || pMethod->IsNoneAccess() ){
200                    compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
201                    return false;
202                }
203                if( !pMethod->GetUserProc().GetParentClass().IsEqualsOrSubClass( pobj_c ) && pMethod->IsProtected() ){
204                    compiler.errorMessenger.Output(110,pUserProc->GetName(),cp);
205                    return false;
206                }
207            }
208        }
209        else{
210            //クラス内部からの呼び出し(継承によるACCESS_NONのみをエラーとする)
211            if( pMethod->IsNoneAccess() ){
212                compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
213                return false;
214            }
215        }
216    }
217
218
219    ///////////////////////////////////////////////////////////////
220    // _System_LocalThisのダミーをセット
221    ///////////////////////////////////////////////////////////////
222
223    char temporary[VN_SIZE]={0};
224    if( pUserProc->GetParentClassPtr() && isStatic == false ){
225        //_System_LocalThis(第一パラメータ)のダミーを作成
226        lstrcpy(temporary,"0,");
227    }
228    if( pUserProc->ReturnType().IsStruct() ){
229        // ※ByRef _System_ReturnValue パラメータのダミーをセット
230        lstrcat(temporary,"0,");
231    }
232
233    if(Parameter[0]=='\0'&&temporary[0])
234        temporary[lstrlen(temporary)-1]=0;
235    else lstrcat(temporary,Parameter);
236
237
238    //パラメータセット前のspオフセットを取得(Newの場合はここにThisポインタが格納されている)
239    int this_sp_offset = pobj_sf->GetNowSp();
240
241
242    ////////////////////////
243    // パラメータをセット
244    ////////////////////////
245
246    //パラメータオブジェクトを生成
247    ParamImpl *pobj_parameter=0;
248    pobj_parameter=new ParamImpl(temporary);
249
250    // デフォルト引数を適用
251    pobj_parameter->ApplyDefaultParameters( pUserProc->RealParams() );
252
253    // 型パラメータを適用
254    pobj_parameter->SetLeftType( leftType );
255
256    //エラーチェック
257    if( !pobj_parameter->ErrorCheck(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetSecondParmNum() ) ){
258        //パラメータにエラーがあるときは処理を終える
259        return false;
260    }
261
262    if(pUserProc->IsMacro()){
263        //マクロ関数の場合は、パラメータ省略を考慮する
264        pobj_parameter->MacroParameterSupport( pUserProc->RealParams() );
265    }
266
267    //スタックフレームに存在する既存のパラメータをバックアップ
268    pobj_parameter->BackupParameter( (int)pUserProc->RealParams().size() );
269
270    //一時オブジェクトを生成
271    pobj_parameter->NewTempParameters( pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum() );
272
273    //レジスタ、スタックフレームにセット
274    pobj_parameter->SetParameter(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum(), pUserProc );
275
276    if( pUserProc->ReturnType().IsStruct() ){
277        //////////////////////////////////////////////////////
278        // 戻り値に構造体インスタンスを持つ場合
279        // ※ByRef _System_ReturnValue パラメータをセット
280        //////////////////////////////////////////////////////
281
282
283        //////////////////////////////////////////////////////
284        /////    レジスタ資源のバックアップ
285        {   BACKUP_REGISTER_RESOURCE
286        //////////////////////////////////////////////////////
287
288            int object_size = pUserProc->ReturnType().GetClass().GetSize();
289
290            //mov rcx,object_size
291            compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RCX,object_size);
292
293            //call calloc
294            extern const UserProc *pSub_calloc;
295            compiler.codeGenerator.op_call(pSub_calloc);
296
297            //mov r13,rax
298            compiler.codeGenerator.op_mov_RR(REG_R13,REG_RAX);
299
300        /////////////////////////////////////////////
301        //////   レジスタ資源を復元
302            RESTORE_REGISTER_RESOURCE
303        }////////////////////////////////////////////
304
305        if( pUserProc->GetParentClassPtr() && isStatic == false ){
306            //mov rdx,r13
307            compiler.codeGenerator.op_mov_RR(REG_RDX,REG_R13);
308        }
309        else{
310            //mov rcx,r13
311            compiler.codeGenerator.op_mov_RR(REG_RCX,REG_R13);
312        }
313    }
314
315
316    if( pUserProc->GetParentClassPtr() && isStatic == false ){
317        ///////////////////////////////
318        // メンバ関数の場合
319        // thisポインタをrcxで受け渡す
320        ///////////////////////////////
321
322        if(ObjectName[0] && (dwFlags&PROCFLAG_NEW)==0){
323            if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
324            else{
325                bool isLiteral, isNeedHeapFreeStructure = false;
326                Type baseType( DEF_OBJECT, *pUserProc->GetParentClassPtr() ) , resultType;
327                if( !TermOpe( ObjectName, baseType, resultType, isLiteral, isNeedHeapFreeStructure, NULL, false, !pMethod->IsConst() ) )
328                {
329                    return false;
330                }
331                if( !resultType.IsObject() )
332                {
333                    compiler.errorMessenger.OutputFatalError();
334                }
335
336                // 実態ポインタをraxにコピー
337                compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX );
338            }
339        }
340        else{
341InClassMember:
342            if(dwFlags&PROCFLAG_NEW){
343                //New演算子によるコンストラクタ呼び出しの場合
344
345                //mov rcx,qword ptr[rsp+offset]     ※スタックフレームを利用
346                pobj_sf->ref_offset_data(REG_RCX, this_sp_offset);
347            }
348            else{
349                //自身のオブジェクトのThisポインタをrcxにコピー
350                SetThisPtrToReg(REG_RCX);
351            }
352        }
353    }
354
355    if( pUserProc->IsVirtual() && !isFixedClass ){
356        int vtblIndex;
357        if( pobj_c->IsInterface() )
358        {
359            // インターフェイス メソッド呼び出し
360
361            int offset_vtbl = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__vtbl" );
362
363            // vtblのポインタを取得
364            //mov r11,qword ptr[rcx+offset_vtbl]
365            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,offset_vtbl,MOD_BASE_DISP8);
366
367            int offset_this = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__this" );
368
369            // インターフェイスの場合は更に__thisを取得する
370            //mov rcx,qword ptr[rcx+offset_this]
371            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,offset_this,MOD_BASE_DISP8);
372
373            int vtblMasterListIndex;
374            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
375            if( vtblMasterListIndex != 0 )
376            {
377                compiler.errorMessenger.OutputFatalError();
378            }
379        }
380        else if( pobj_c->IsComInterface() )
381        {
382            // COMインターフェイス メソッド呼び出し
383
384            //仮想関数(オブジェクトメソッド)呼び出し
385            // pObj -> vtbl1 -> func1
386            //               -> func2
387            //               -> func3
388
389            int vtblMasterListIndex;
390            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
391
392            // vtblのポインタを取得
393            //mov r11,qword ptr[rcx]
394            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE);        }
395        else
396        {
397            //仮想関数(オブジェクトメソッド)呼び出し
398            // pObj -> vtbl_master_list -> vtbl1 -> func1
399            //                                   -> func2
400            //                                   -> func3
401            //                          -> vtbl2 -> func1
402            //                                   -> func2
403            //                                   -> func3
404
405            int vtblMasterListIndex;
406            pobj_c->GetVtblMasterListIndexAndVtblIndex( pUserProc, vtblMasterListIndex, vtblIndex );
407
408            // vtblマスターリストのポインタを取得
409            //mov r11,qword ptr[rcx+sizeof(com_vtbl)]
410            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,PTR_SIZE,MOD_BASE_DISP8);
411
412            // vtblのポインタを取得
413            //mov r11,dword ptr[r11+vtblMasterListIndex]
414            compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_R11, REG_R11, vtblMasterListIndex*PTR_SIZE, MOD_BASE_DISP32 );
415        }
416
417        //call qword ptr[r11+func_index]
418        if( vtblIndex * PTR_SIZE <= 0x7F ){
419            compiler.codeGenerator.PutOld(
420                (char)0x41,
421                (char)0xFF,
422                (char)0x53,
423                (char)(vtblIndex*PTR_SIZE)
424            );
425        }
426        else{
427            compiler.codeGenerator.PutOld(
428                (char)0x41,
429                (char)0xFF,
430                (char)0x93,
431                (long)(vtblIndex*PTR_SIZE)
432            );
433        }
434    }
435    else{
436        //通常呼び出し
437
438        //call ProcAddr
439        compiler.codeGenerator.op_call(pUserProc);
440    }
441
442    /* 64コンパイラでは不要
443    if(pDllProc->bCdecl){
444        //add esp,ParmSize
445    }*/
446
447
448    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
449    pobj_BlockReg->clear();
450
451    //一時オブジェクトを破棄
452    pobj_parameter->DeleteTempParameters();
453
454    //スタックフレームに存在する既存のパラメータを復元
455    pobj_parameter->RestoreParameter( (int)pUserProc->RealParams().size() );
456
457    //パラメータオブジェクトを破棄
458    delete pobj_parameter;
459
460    return true;
461}
462
463bool Opcode_CallDllProc( const char *lpszParms, DllProc *pDllProc ){
464
465    extern BOOL bDebugSupportProc;
466    if( compiler.IsDebug() && bDebugSupportProc==0 && pDllProc->IsEqualSymbol( LexicalAnalyzer::FullNameToSymbol( "DebugBreak" ) ) )
467    {
468        Call_DebugSys_SaveContext();
469    }
470
471
472    ////////////////////////
473    // パラメータのセット
474    ////////////////////////
475
476    //パラメータオブジェクトを生成
477    ParamImpl *pobj_parameter=0;
478    pobj_parameter=new ParamImpl(lpszParms);
479
480    // デフォルト引数を適用
481    pobj_parameter->ApplyDefaultParameters( pDllProc->Params() );
482
483    //エラーチェック
484    if( !pobj_parameter->ErrorCheck( pDllProc->GetName(), pDllProc->Params() ) ){
485        //パラメータにエラーがあるときは処理を終える
486        return false;
487    }
488
489    //スタックフレームに存在する既存のパラメータをバックアップ
490    pobj_parameter->BackupParameter( (int)pDllProc->Params().size() );
491
492    //一時オブジェクトを生成
493    pobj_parameter->NewTempParameters( pDllProc->GetName(), pDllProc->Params() );
494
495    //レジスタ、スタックフレームにセット
496    pobj_parameter->SetParameter(pDllProc->GetName(), pDllProc->Params() );
497
498
499    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
500    pobj_BlockReg->clear();
501
502
503    //動的リンクされたプロシージャの呼び出し
504
505    //call dword ptr[ImportTable]
506    compiler.codeGenerator.op_call( pDllProc );
507
508    /* 64コンパイラでは不要
509    if(pDllProc->bCdecl){
510        //add esp,ParmSize
511    }*/
512
513    //一時オブジェクトを破棄
514    pobj_parameter->DeleteTempParameters();
515
516    //スタックフレームに存在する既存のパラメータを復元
517    pobj_parameter->RestoreParameter( (int)pDllProc->Params().size() );
518
519    //パラメータオブジェクトを破棄
520    delete pobj_parameter;
521
522    return true;
523}
524
525void Opcode_CallDelegate( const Delegate &dg, const char *methodPtrValueStr, const char *objPtrValueStr, const char *params )
526{
527    extern BOOL bDebugSupportProc;
528    if( compiler.IsDebug() && bDebugSupportProc == 0 )
529    {
530        Call_DebugSys_SaveContext();
531    }
532
533
534    ///////////////////////////////////////////////////////////////
535    // _System_LocalThisのダミーをセット
536    ///////////////////////////////////////////////////////////////
537
538    char temporary[VN_SIZE]={0};
539    bool isDynamicCall = false;
540    if( objPtrValueStr && objPtrValueStr[0] ){
541        //_System_LocalThis(第一パラメータ)のダミーを作成
542        lstrcpy(temporary,"0,");
543
544        isDynamicCall = true;
545    }
546    if( dg.ReturnType().IsStruct() ){
547        // ※ByRef _System_ReturnValue パラメータのダミーをセット
548        lstrcat(temporary,"0,");
549    }
550
551    if(params[0]=='\0'&&temporary[0])
552        temporary[lstrlen(temporary)-1]=0;
553    else lstrcat(temporary,params);
554
555    const Parameters *pParams = &dg.Params();
556    if( isDynamicCall )
557    {
558        pParams = &dg.GetDynamicParams();
559    }
560
561
562    ParamImpl *pobj_parameter = new ParamImpl( temporary );
563
564    //スタックフレームに存在する既存のパラメータをバックアップ
565    pobj_parameter->BackupParameter( (int)pParams->size() );
566
567    //一時オブジェクトを生成
568    pobj_parameter->NewTempParameters( dg.GetName(), *pParams );
569
570    //レジスタ、スタックフレームにセット
571    pobj_parameter->SetParameter( dg.GetName(), *pParams );
572
573
574    if( objPtrValueStr && objPtrValueStr[0] )
575    {
576        RELATIVE_VAR RelativeVar;
577        //Constアクセスが不可能なメソッドの場合
578        if( !GetVarOffsetReadWrite( objPtrValueStr, &RelativeVar, Type() ) ){
579            Jenga::Throw( "Opcode_CallDelegate関数内で呼ばれるGetVarOffsetReadWrite関数に失敗" );
580            return;
581        }
582
583        SetVarPtrToReg(REG_RCX,&RelativeVar);
584
585        // 参照を実体ポインタにする
586        //mov rcx,qword ptr[rcx]
587        compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE);
588    }
589
590
591    {
592        ////////////////////////
593        // call
594        ////////////////////////
595        RELATIVE_VAR RelativeVar;
596        GetVarOffsetReadOnly( methodPtrValueStr, &RelativeVar, Type() );
597        SetVarPtrToReg(REG_RAX,&RelativeVar);
598
599        //mov rax,qword ptr[rax]
600        compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_RAX,0,MOD_BASE);
601
602        //call rax
603        compiler.codeGenerator.PutOld(
604            (char)0xFF,
605            (char)0xD0
606        );
607    }
608
609
610    //レジスタのブロッキングを解除        ※パラメータセット時にロックされたレジスタ
611    pobj_BlockReg->clear();
612
613    //一時オブジェクトを破棄
614    pobj_parameter->DeleteTempParameters();
615
616    //スタックフレームに存在する既存のパラメータを復元
617    pobj_parameter->RestoreParameter( (int)pParams->size() );
618
619    //パラメータオブジェクトを破棄
620    delete pobj_parameter;
621}
Note: See TracBrowser for help on using the repository browser.