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

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

64bit版を最新の状態にした

File size: 17.0 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 compiler.errorMessenger.Output(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 compiler.errorMessenger.Output(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 compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
192 return false;
193 }
194 }
195 else{
196 if( pMethod->IsPrivate()
197 || pMethod->IsNoneAccess() ){
198 compiler.errorMessenger.Output(109,pUserProc->GetName(),cp);
199 return false;
200 }
201 if( !pMethod->GetUserProc().GetParentClass().IsEqualsOrSubClass( pobj_c ) && pMethod->IsProtected() ){
202 compiler.errorMessenger.Output(110,pUserProc->GetName(),cp);
203 return false;
204 }
205 }
206 }
207 else{
208 //クラス内部からの呼び出し(継承によるACCESS_NONのみをエラーとする)
209 if( pMethod->IsNoneAccess() ){
210 compiler.errorMessenger.Output(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 compiler.errorMessenger.OutputFatalError();
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 compiler.errorMessenger.OutputFatalError();
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.