source: dev/trunk/ab5.0/abdev/BasicCompiler64/Compile_CallProc.cpp @ 463

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

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

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