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