source: dev/BasicCompiler64/Compile_CallProc.cpp@ 94

Last change on this file since 94 was 77, checked in by dai_9181, 18 years ago

デフォルトパラメータに対応。

File size: 11.9 KB
RevLine 
[3]1#include "../BasicCompiler_Common/common.h"
2#include "Opcode.h"
3
4//ローカル変数アドレススケジュール
5DWORD *pLocalVarAddrSchedule;
6int LocalVarAddrScheduleNum;
7
8void Call_DebugSys_SaveContext(){
9 //call _System_GetEip
[75]10 extern UserProc *pSub_System_GetEip;
[3]11 op_call(pSub_System_GetEip);
12
13 //mov rdx,rax
[64]14 op_mov_RR(REG_RDX,REG_RAX);
[3]15
16 //mov rcx,rsp
[64]17 op_mov_RR(REG_RCX,REG_RSP);
[3]18
19 //call _DebugSys_SaveContext
[75]20 extern UserProc *pSub_DebugSys_SaveContext;
[3]21 op_call(pSub_DebugSys_SaveContext);
22}
23
24void AddLocalVarAddrSchedule(){
25 extern HANDLE hHeap;
26
27 //ローカル変数アドレススケジュールに追加する
28 pLocalVarAddrSchedule=(DWORD *)HeapReAlloc(hHeap,0,pLocalVarAddrSchedule,(LocalVarAddrScheduleNum+1)*sizeof(DWORD));
29 pLocalVarAddrSchedule[LocalVarAddrScheduleNum]=obp;
30 LocalVarAddrScheduleNum++;
31}
32
33
[75]34bool Opcode_CallProcPtr( const char *variable, const char *lpszParms,ProcPointer *pProcPointer){
[3]35
36 extern BOOL bDebugCompile;
37 extern BOOL bDebugSupportProc;
38 if(bDebugCompile&&bDebugSupportProc==0)
39 Call_DebugSys_SaveContext();
40
41
42 ////////////////////////
43 // パラメータのセット
44 ////////////////////////
45
46 //パラメータオブジェクトを生成
[71]47 ParamImpl *pobj_parameter=0;
[75]48 pobj_parameter=new ParamImpl(lpszParms);
[3]49
[77]50 // デフォルト引数を適用
51 pobj_parameter->ApplyDefaultParameters( pProcPointer->Params() );
52
[3]53 //エラーチェック
[75]54 if( !pobj_parameter->ErrorCheck(variable,pProcPointer->Params() ) ){
[31]55 //パラメータにエラーがあるときは処理を終える
[75]56 return false;
[31]57 }
[3]58
59 //スタックフレームに存在する既存のパラメータをバックアップ
[75]60 pobj_parameter->BackupParameter( (int)pProcPointer->Params().size() );
[3]61
[20]62 //一時オブジェクトを生成
[75]63 pobj_parameter->NewTempParameters( variable,pProcPointer->Params() );
[20]64
[3]65 //レジスタ、スタックフレームにセット
[75]66 pobj_parameter->SetParameter(variable,pProcPointer->Params() );
[3]67
68
69
70 RELATIVE_VAR RelativeVar;
[75]71 GetVarOffsetReadOnly(variable,&RelativeVar,Type());
[3]72 SetVarPtrToReg(REG_RAX,&RelativeVar);
73
74 //mov rax,qword ptr[rax]
75 op_mov_RM(sizeof(_int64),REG_RAX,REG_RAX,0,MOD_BASE);
76
77 //call rax
78 OpBuffer[obp++]=(char)0xFF;
79 OpBuffer[obp++]=(char)0xD0;
80
81
82 //レジスタのブロッキングを解除 ※パラメータセット時にロックされたレジスタ
83 pobj_BlockReg->clear();
84
[20]85 //一時オブジェクトを破棄
86 pobj_parameter->DeleteTempParameters();
87
[3]88 //スタックフレームに存在する既存のパラメータを復元
[75]89 pobj_parameter->RestoreParameter( (int)pProcPointer->Params().size() );
[3]90
91 //パラメータオブジェクトを破棄
92 delete pobj_parameter;
93
[75]94 return true;
[3]95}
96
[75]97bool Opcode_CallProc(const char *Parameter,UserProc *pUserProc,DWORD dwFlags,const char *ObjectName,int RefType){
[51]98 int i2;
[3]99
[75]100 if( pUserProc->IsMacro() ){
101 if( lstrcmpi( pUserProc->GetName().c_str(), "Print" ) == 0 ){
[3]102 Opcode_Print(Parameter,0);
[75]103 return true;
[3]104 }
[75]105 if( lstrcmpi( pUserProc->GetName().c_str(), "Input" ) == 0 ){
[3]106 Opcode_Input(Parameter);
[75]107 return true;
[3]108 }
[75]109 if( lstrcmpi( pUserProc->GetName().c_str(), "Write" ) == 0 ){
[3]110 Opcode_Print(Parameter,1);
[75]111 return true;
[3]112 }
113 }
114
[75]115 pUserProc->Using();
[3]116
[47]117 bool isStatic = false;
[75]118 const CClass *pobj_c = NULL;
[18]119 CMethod *pMethod = NULL;
[75]120 if( pUserProc->GetParentClassPtr() ){
[3]121 //クラスのメンバ関数を呼び出す場合はアクセスチェックを行う
122 if(ObjectName[0]){
123 if(lstrcmpi(ObjectName,"Super")==0){
[27]124 //クラスメンバ関数内から基底クラスの呼び出し
[3]125 pobj_c=pobj_CompilingClass;
126 }
127 else{
[47]128 //"->"によってオブジェクトを指定する通常のメンバ関数呼び出し
[75]129 Type varType;
130 GetVarType( ObjectName, varType, false );
131 pobj_c = &varType.GetClass();
132 if( NATURAL_TYPE( varType.GetBasicType() ) != DEF_OBJECT ){
[47]133 pobj_c=pobj_DBClass->check(ObjectName);
134 if( pobj_c ){
135 isStatic = true;
136 }
137 else{
138 SetError(300,NULL,cp);
139 }
[3]140 }
141 }
142 }
143 else{
144 if(dwFlags&PROCFLAG_NEW){
145 //New演算子によるコンストラクタ呼び出し
[75]146 pobj_c=pUserProc->GetParentClassPtr();
[3]147 }
148 else{
149 //クラスメンバ関数内から同一クラスのメンバ関数の呼び出し
150 pobj_c=pobj_CompilingClass;
151 }
152 }
153
[18]154
155 /////////////////////////////////
156 // メソッド情報を取得
157 /////////////////////////////////
[27]158 pMethod = NULL;
[75]159 if( ! isStatic ) pMethod = pobj_c->GetMethodInfo( pUserProc );
[27]160 if( ! pMethod ){
[18]161 //動的メソッドが取得できなかったときは静的メソッドを当たる
[75]162 pMethod = pobj_c->GetStaticMethodInfo( pUserProc );
[18]163 if( !pMethod ){
164 SetError(300,NULL,cp);
[75]165 return false;
[3]166 }
[26]167
168 //静的メンバ
[47]169 isStatic = true;
[3]170 }
171
172
173 //////////////////////////////
174 // アクセスエラーチェック
175 //////////////////////////////
[18]176 DWORD dwAccess = pMethod->dwAccess;
[3]177
178 if(ObjectName[0]){
179 //外部からの呼び出し
180 if(pobj_c==pobj_CompilingClass){
181 //同一クラスオブジェクトの場合はプライベートアクセスを容認する
182 if(dwAccess==ACCESS_NON){
[75]183 SetError(109,pUserProc->GetName(),cp);
184 return false;
[3]185 }
186 }
187 else{
188 if(dwAccess==ACCESS_PRIVATE||
189 dwAccess==ACCESS_NON){
[75]190 SetError(109,pUserProc->GetName(),cp);
191 return false;
[3]192 }
193 if(dwAccess==ACCESS_PROTECTED){
[75]194 SetError(110,pUserProc->GetName(),cp);
195 return false;
[3]196 }
197 }
198 }
199 else{
200 //クラス内部からの呼び出し(継承によるACCESS_NONのみをエラーとする)
201 if(dwAccess==ACCESS_NON){
[75]202 SetError(109,pUserProc->GetName(),cp);
203 return false;
[3]204 }
205 }
206 }
207
208
209 ///////////////////////////////////////////////////////////////
[64]210 // _System_LocalThisのダミーをセット
[3]211 ///////////////////////////////////////////////////////////////
212
213 char temporary[VN_SIZE]={0};
[75]214 if( pUserProc->GetParentClassPtr() && isStatic == false ){
[3]215 //_System_LocalThis(第一パラメータ)のダミーを作成
216 lstrcpy(temporary,"0,");
217 }
218
219 if(Parameter[0]=='\0'&&temporary[0])
220 temporary[lstrlen(temporary)-1]=0;
221 else lstrcat(temporary,Parameter);
222
223
[64]224 //パラメータセット前のspオフセットを取得(Newの場合はここにThisポインタが格納されている)
225 int this_sp_offset = pobj_sf->GetNowSp();
226
227
[3]228 ////////////////////////
229 // パラメータをセット
230 ////////////////////////
231
232 //パラメータオブジェクトを生成
[71]233 ParamImpl *pobj_parameter=0;
234 pobj_parameter=new ParamImpl(temporary);
[3]235
[77]236 // デフォルト引数を適用
237 pobj_parameter->ApplyDefaultParameters( pUserProc->RealParams() );
238
[3]239 //エラーチェック
[75]240 if( !pobj_parameter->ErrorCheck(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetSecondParmNum() ) ){
[31]241 //パラメータにエラーがあるときは処理を終える
[75]242 return false;
[31]243 }
[3]244
[75]245 if(pUserProc->IsMacro()){
[3]246 //マクロ関数の場合は、パラメータ省略を考慮する
[75]247 pobj_parameter->MacroParameterSupport( pUserProc->RealParams() );
[3]248 }
249
250 //スタックフレームに存在する既存のパラメータをバックアップ
[75]251 pobj_parameter->BackupParameter( (int)pUserProc->RealParams().size() );
[3]252
[20]253 //一時オブジェクトを生成
[75]254 pobj_parameter->NewTempParameters( pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum() );
[20]255
[3]256 //レジスタ、スタックフレームにセット
[75]257 pobj_parameter->SetParameter(pUserProc->GetName(),pUserProc->RealParams(),pUserProc->GetRealSecondParmNum() );
[3]258
[75]259 if(pUserProc->ReturnType().IsStruct() ){
[3]260 //////////////////////////////////////////////////////
[64]261 // 戻り値に構造体インスタンスを持つ場合
262 // ※ByRef _System_ReturnValue パラメータをセット
[3]263 //////////////////////////////////////////////////////
264
265
266 //////////////////////////////////////////////////////
267 ///// レジスタ資源のバックアップ
268 { BACKUP_REGISTER_RESOURCE
269 //////////////////////////////////////////////////////
270
[75]271 int object_size = pUserProc->ReturnType().GetClass().GetSize();
[3]272
273 //mov rcx,object_size
274 op_mov_RV(sizeof(_int64),REG_RCX,object_size);
275
276 //call calloc
[75]277 extern UserProc *pSub_calloc;
[3]278 op_call(pSub_calloc);
279
280 //mov r13,rax
281 op_mov_RR(REG_R13,REG_RAX);
282
283 /////////////////////////////////////////////
284 ////// レジスタ資源を復元
285 RESTORE_REGISTER_RESOURCE
286 }////////////////////////////////////////////
287
[75]288 if( pUserProc->GetParentClassPtr() && isStatic == false ){
[3]289 //mov rdx,r13
290 op_mov_RR(REG_RDX,REG_R13);
291 }
292 else{
293 //mov rcx,r13
294 op_mov_RR(REG_RCX,REG_R13);
295 }
296 }
297
298
[75]299 if( pUserProc->GetParentClassPtr() && isStatic == false ){
[3]300 ///////////////////////////////
301 // メンバ関数の場合
302 // thisポインタをrcxで受け渡す
303 ///////////////////////////////
304
305 if(ObjectName[0]){
306 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
307 else{
308 RELATIVE_VAR RelativeVar;
[18]309 if( pMethod->isConst ){
310 //Constアクセスが可能なメソッドの場合
[75]311 if( !GetVarOffsetReadOnly( ObjectName, &RelativeVar, Type() ) ){
312 return false;
313 }
[18]314 }
315 else{
316 //Constアクセスが不可能なメソッドの場合
[75]317 if( !GetVarOffsetReadWrite( ObjectName, &RelativeVar, Type() ) ){
318 return false;
319 }
[18]320 }
321
[3]322 SetVarPtrToReg(REG_RCX,&RelativeVar);
323
[64]324 // 参照を実体ポインタにする
325 //mov rcx,qword ptr[rcx]
326 op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE);
[3]327 }
328 }
329 else{
330InClassMember:
331 if(dwFlags&PROCFLAG_NEW){
332 //New演算子によるコンストラクタ呼び出しの場合
333
334 //mov rcx,qword ptr[rsp+offset] ※スタックフレームを利用
[64]335 pobj_sf->ref_offset_data(REG_RCX, this_sp_offset);
[3]336 }
337 else{
338 //自身のオブジェクトのThisポインタをrcxにコピー
339 SetThisPtrToReg(REG_RCX);
340 }
341 }
342 }
343
[75]344 if( pUserProc->IsVirtual() ){
[3]345 //仮想関数(オブジェクトメソッド)呼び出し
346 //pObj->func_table->func1
347 // ->func2
348 // ->func3
349
350 //mov r11,qword ptr[rcx]
351 op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE);
352
[75]353 i2 = pobj_c->GetFuncNumInVtbl( pUserProc );
[3]354
355 //call qword ptr[r11+func_index]
356 if(i2*PTR_SIZE<=0x7F){
357 OpBuffer[obp++]=(char)0x41;
358 OpBuffer[obp++]=(char)0xFF;
359 OpBuffer[obp++]=(char)0x53;
360 OpBuffer[obp++]=(char)(i2*PTR_SIZE);
361 }
362 else{
363 OpBuffer[obp++]=(char)0x41;
364 OpBuffer[obp++]=(char)0xFF;
365 OpBuffer[obp++]=(char)0x93;
366 *((long *)(OpBuffer+obp))=i2*PTR_SIZE;
367 obp+=sizeof(long);
368 }
369 }
370 else{
371 //通常呼び出し
372
373 //call ProcAddr
[75]374 op_call(pUserProc);
[3]375 }
376
377 /* 64コンパイラでは不要
[75]378 if(pDllProc->bCdecl){
[3]379 //add esp,ParmSize
380 }*/
381
382
383 //レジスタのブロッキングを解除 ※パラメータセット時にロックされたレジスタ
384 pobj_BlockReg->clear();
385
[20]386 //一時オブジェクトを破棄
387 pobj_parameter->DeleteTempParameters();
388
[3]389 //スタックフレームに存在する既存のパラメータを復元
[75]390 pobj_parameter->RestoreParameter( (int)pUserProc->RealParams().size() );
[3]391
392 //パラメータオブジェクトを破棄
393 delete pobj_parameter;
[75]394
395 return true;
[3]396}
397
[75]398bool Opcode_CallDllProc( const char *lpszParms, DllProc *pDllProc ){
[3]399
400 extern BOOL bDebugCompile;
401 extern BOOL bDebugSupportProc;
[75]402 if(bDebugCompile&&bDebugSupportProc==0&& pDllProc->GetName() != "DebugBreak" ){
[3]403 Call_DebugSys_SaveContext();
[75]404 }
[3]405
406
407 ////////////////////////
408 // パラメータのセット
409 ////////////////////////
410
411 //パラメータオブジェクトを生成
[71]412 ParamImpl *pobj_parameter=0;
[75]413 pobj_parameter=new ParamImpl(lpszParms);
[3]414
[77]415 // デフォルト引数を適用
416 pobj_parameter->ApplyDefaultParameters( pDllProc->Params() );
417
[3]418 //エラーチェック
[75]419 if( !pobj_parameter->ErrorCheck( pDllProc->GetName(), pDllProc->Params() ) ){
[31]420 //パラメータにエラーがあるときは処理を終える
[75]421 return false;
[31]422 }
[3]423
424 //スタックフレームに存在する既存のパラメータをバックアップ
[75]425 pobj_parameter->BackupParameter( (int)pDllProc->Params().size() );
[3]426
[45]427 //一時オブジェクトを生成
[75]428 pobj_parameter->NewTempParameters( pDllProc->GetName(), pDllProc->Params() );
[45]429
[3]430 //レジスタ、スタックフレームにセット
[75]431 pobj_parameter->SetParameter(pDllProc->GetName(), pDllProc->Params() );
[3]432
433
434 //レジスタのブロッキングを解除 ※パラメータセット時にロックされたレジスタ
435 pobj_BlockReg->clear();
436
437
438 //動的リンクされたプロシージャの呼び出し
439
440 //call dword ptr[ImportTable]
[75]441 op_call( pDllProc );
[3]442
443 /* 64コンパイラでは不要
[75]444 if(pDllProc->bCdecl){
[3]445 //add esp,ParmSize
446 }*/
447
[45]448 //一時オブジェクトを破棄
449 pobj_parameter->DeleteTempParameters();
450
[3]451 //スタックフレームに存在する既存のパラメータを復元
[75]452 pobj_parameter->RestoreParameter( (int)pDllProc->Params().size() );
[3]453
454 //パラメータオブジェクトを破棄
455 delete pobj_parameter;
456
[75]457 return true;
[3]458}
Note: See TracBrowser for help on using the repository browser.