source: dev/trunk/abdev/BasicCompiler64/Compile_CallProc.cpp@ 201

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