source: dev/BasicCompiler32/Compile_CallProc.cpp@ 31

Last change on this file since 31 was 31, checked in by dai_9181, 17 years ago

_System_LocalThis(見えないThisポインタパラメータ)を通常のパラメータ保有領域ではなく、リアルパラメータ保有領域に移動した。
メソッドとグローバル関数のオーバーロードに対応(DLL関数オーバーロードには未対応)。

File size: 13.0 KB
Line 
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
10 extern SUBINFO *pSub_System_GetEip;
11 op_call(pSub_System_GetEip);
12
13 //push eax
14 op_push(REG_EAX);
15
16 //push ebp
17 op_push(REG_EBP);
18
19 //call _DebugSys_SaveContext
20 extern SUBINFO *pSub_DebugSys_SaveContext;
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}
32int CallProc(int idProc,void *pInfo,char *name,char *Parameter,LONG_PTR *plpRetIndex){
33 int ret_type;
34
35 if(idProc==PROC_DEFAULT){
36 /////////////////////
37 // ユーザー定義関数
38 /////////////////////
39
40 SUBINFO *psi;
41 psi=(SUBINFO *)pInfo;
42
43 //GetSubHash内でエラー提示が行われた場合
44 if(psi==(SUBINFO *)-1) return -1;
45
46
47 //オブジェクト名を取得
48 char ObjectName[VN_SIZE];
49 int RefType;
50 SplitObjectName(name,ObjectName,&RefType);
51
52
53 ////////////////////////
54 // オーバーロードを解決
55 ////////////////////////
56
57 SUBINFO **ppsi;
58 int num;
59 ppsi=GetOverloadSubHash(name,&num);
60 if(num){
61 //オーバーロードを解決
62 psi=OverloadSolutionWithStrParam(name,ppsi,num,Parameter,ObjectName,NULL);
63 HeapDefaultFree(ppsi);
64
65 if(!psi) return 0;
66 }
67
68
69 Opcode_CallProc(Parameter,psi,0,ObjectName,RefType);
70 if( plpRetIndex ){
71 *plpRetIndex = psi->u.ReturnIndex;
72 }
73 return psi->ReturnType;
74 }
75 else if(idProc==PROC_DLL){
76 /////////////////////////
77 // DLL関数
78 /////////////////////////
79 DECLAREINFO *pdi;
80 pdi=(DECLAREINFO *)pInfo;
81
82 ret_type=Opcode_CallDllProc(Parameter,pdi,plpRetIndex);
83 }
84 else if(idProc==PROC_BUILTIN){
85 /////////////////////////
86 // 組み込み関数
87 /////////////////////////
88 int FuncId;
89 FuncId=(int)(_int64)pInfo;
90
91 ret_type=Opcode_CallFunc(Parameter,FuncId);
92 }
93 else if(idProc==PROC_PTR){
94 /////////////////
95 // 関数ポインタ
96 /////////////////
97
98 LONG_PTR lpIndex;
99 GetVarType(name,&lpIndex,0);
100
101 extern PROCPTRINFO *pProcPtrInfo;
102 ret_type=Opcode_CallProcPtr(name,Parameter,&pProcPtrInfo[lpIndex],plpRetIndex);
103 }
104
105 return ret_type;
106}
107
108BOOL CallPropertyMethod(char *variable,char *RightSide,TYPEINFO *pRetTypeInfo){
109 //プロパティ用のメソッドを呼び出す
110
111 //配列要素を取得
112 char VarName[VN_SIZE],ArrayElements[VN_SIZE];
113 GetArrayElement(variable,VarName,ArrayElements);
114
115 //オブジェクト名を取得
116 char ObjectName[VN_SIZE];
117 int RefType;
118 SplitObjectName(VarName,ObjectName,&RefType);
119
120 //オーバーロード用の関数リストを作成
121 SUBINFO **ppsi;
122 int num;
123 ppsi=GetOverloadSubHash(VarName,&num);
124 if(num==0){
125 return 0;
126 }
127
128 //パラメータを整備
129 char *Parameter;
130 Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(RightSide)+32);
131 lstrcpy(Parameter,ArrayElements);
132 if(RightSide){
133 if(Parameter[0]&&RightSide[0]) lstrcat(Parameter,",");
134 lstrcat(Parameter,RightSide);
135 }
136
137 //オーバーロードを解決
138 SUBINFO *psi;
139 psi=OverloadSolutionWithStrParam(VarName,ppsi,num,Parameter,ObjectName,NULL);
140 HeapDefaultFree(ppsi);
141
142 if(psi){
143 //呼び出し
144 Opcode_CallProc(Parameter,psi,0,ObjectName,RefType);
145
146 if(pRetTypeInfo){
147 pRetTypeInfo->type = psi->ReturnType;
148 pRetTypeInfo->u.lpIndex = psi->u.ReturnIndex;
149 }
150 }
151
152 HeapDefaultFree(Parameter);
153
154 return 1;
155}
156
157
158int Opcode_CallProcPtr(char *variable,char *Parameter,PROCPTRINFO *pi,LONG_PTR *plpIndex){
159 extern HANDLE hHeap;
160 int i;
161
162
163 extern BOOL bDebugCompile;
164 extern BOOL bDebugSupportProc;
165 if(bDebugCompile&&bDebugSupportProc==0)
166 Call_DebugSys_SaveContext();
167
168
169 ////////////////////////
170 // パラメータのセット
171 ////////////////////////
172
173 //パラメータオブジェクトを生成
174 CParameter *pobj_parameter=0;
175 pobj_parameter=new CParameter(Parameter);
176
177 //エラーチェック
178 if( !pobj_parameter->ErrorCheck(variable,pi->pParmInfo,pi->ParmNum,pi->ParmNum) ){
179 //パラメータにエラーがあるときは処理を終える
180 return pi->ReturnType;
181 }
182
183 //一時オブジェクトを生成
184 pobj_parameter->NewTempParameters( variable,pi->pParmInfo,pi->ParmNum,pi->ParmNum );
185
186 //レジスタ、スタックフレームにセット
187 pobj_parameter->SetParameter(variable,pi->pParmInfo,pi->ParmNum,pi->ParmNum);
188
189
190
191 ////////////////////////
192 // call
193 ////////////////////////
194 RELATIVE_VAR RelativeVar;
195 LONG_PTR lp;
196 GetVarOffsetReadOnly(variable,&i,&RelativeVar,&lp);
197 SetVarPtrToEax(&RelativeVar);
198
199 //mov eax,dword ptr[eax]
200 OpBuffer[obp++]=(char)0x8B;
201 OpBuffer[obp++]=(char)0x00;
202
203 //call eax
204 OpBuffer[obp++]=(char)0xFF;
205 OpBuffer[obp++]=(char)0xD0;
206
207
208
209 //一時オブジェクトを破棄
210 pobj_parameter->DeleteTempParameters();
211
212 //パラメータオブジェクトを破棄
213 delete pobj_parameter;
214
215 if(plpIndex) *plpIndex=pi->u.ReturnIndex;
216
217 return pi->ReturnType;
218}
219
220void Opcode_CallProc(char *Parameter,SUBINFO *psi,DWORD dwFlags,char *ObjectName,int RefType){
221 int i,i2;
222
223 if(psi->dwType==SUBTYPE_MACRO){
224 if(lstrcmpi(psi->name,"Print")==0){
225 Opcode_Print(Parameter,0);
226 return;
227 }
228 if(lstrcmpi(psi->name,"Input")==0){
229 Opcode_Input(Parameter);
230 return;
231 }
232 if(lstrcmpi(psi->name,"Write")==0){
233 Opcode_Print(Parameter,1);
234 return;
235 }
236 }
237
238 psi->bUse=1;
239
240 BOOL bStatic=0;
241 CClass *pobj_c = NULL;
242 CMethod *pMethod = NULL;
243 if(psi->pobj_ParentClass){
244 //クラスのメンバ関数を呼び出す場合はアクセスチェックを行う
245 if(ObjectName[0]){
246 if(lstrcmpi(ObjectName,"Super")==0){
247 //クラスメンバ関数内から基底クラスの呼び出し
248 pobj_c=pobj_CompilingClass;
249 }
250 else{
251 pobj_c=pobj_DBClass->check(ObjectName);
252 if(pobj_c){
253 //静的メンバ
254 bStatic=1;
255 }
256 else{
257 //"->"によってオブジェクトを指定する通常のメンバ関数呼び出し
258 GetVarType(ObjectName,(LONG_PTR *)&pobj_c,1);
259 }
260 }
261 }
262 else{
263 if(dwFlags&PROCFLAG_NEW){
264 //New演算子によるコンストラクタ呼び出し
265 pobj_c=psi->pobj_ParentClass;
266 }
267 else{
268 //クラスメンバ関数内から同一クラスのメンバ関数の呼び出し
269 pobj_c=pobj_CompilingClass;
270 }
271 }
272
273
274 /////////////////////////////////
275 // メソッド情報を取得
276 /////////////////////////////////
277 pMethod = NULL;
278 if( ! bStatic ) pMethod = pobj_c->GetMethodInfo( psi );
279 if( ! pMethod ){
280 //動的メソッドが取得できなかったときは静的メソッドを当たる
281 pMethod = pobj_c->GetStaticMethodInfo( psi );
282 if( !pMethod ){
283 SetError(300,NULL,cp);
284 return;
285 }
286
287 //静的メンバ
288 bStatic=1;
289 }
290
291
292 //////////////////////////////
293 // アクセスエラーチェック
294 //////////////////////////////
295 DWORD dwAccess = pMethod->dwAccess;
296
297 if(ObjectName[0]){
298 //外部からの呼び出し
299 if(pobj_c==pobj_CompilingClass){
300 //同一クラスオブジェクトの場合はプライベートアクセスを容認する
301 if(dwAccess==ACCESS_NON){
302 SetError(109,psi->name,cp);
303 return;
304 }
305 }
306 else{
307 if(dwAccess==ACCESS_PRIVATE||
308 dwAccess==ACCESS_NON){
309 SetError(109,psi->name,cp);
310 return;
311 }
312 if(dwAccess==ACCESS_PROTECTED){
313 SetError(110,psi->name,cp);
314 return;
315 }
316 }
317 }
318 else{
319 //クラス内部からの呼び出し(継承によるACCESS_NONのみをエラーとする)
320 if(dwAccess==ACCESS_NON){
321 SetError(109,psi->name,cp);
322 return;
323 }
324 }
325 }
326
327
328
329 ///////////////////////////////////////////////////////////////
330 // _System_LocalThis、_System_ReturnObjectのダミーをセット
331 ///////////////////////////////////////////////////////////////
332
333 char temporary[VN_SIZE]={0};
334 if(psi->pobj_ParentClass&&bStatic==0){
335 //_System_LocalThis(第一パラメータ)のダミーを作成
336 lstrcpy(temporary,"0,");
337 }
338
339 if(psi->ReturnType==DEF_OBJECT){
340 //_System_ReturnObject(第一または第二パラメータのダミーを作成)
341 sprintf(temporary+lstrlen(temporary),"%c%c0,",1,ESC_BYVAL);
342 }
343
344 if(Parameter[0]=='\0'&&temporary[0])
345 temporary[lstrlen(temporary)-1]=0;
346 else lstrcat(temporary,Parameter);
347
348
349
350 ////////////////////////
351 // パラメータをセット
352 ////////////////////////
353
354 //パラメータオブジェクトを生成
355 CParameter *pobj_parameter=0;
356 pobj_parameter=new CParameter(temporary);
357
358 //エラーチェック
359 if( !pobj_parameter->ErrorCheck(psi->name,psi->pRealParmInfo,psi->RealParmNum,psi->RealSecondParmNum) ){
360 //パラメータにエラーがあるときは処理を終える
361 return;
362 }
363
364 if(psi->dwType==SUBTYPE_MACRO){
365 //マクロ関数の場合は、パラメータ省略を考慮する
366 pobj_parameter->MacroParameterSupport(psi->pRealParmInfo);
367 }
368
369 //一時オブジェクトを生成
370 pobj_parameter->NewTempParameters( psi->name,psi->pRealParmInfo,psi->RealParmNum,psi->RealSecondParmNum );
371
372 //レジスタ、スタックフレームにセット
373 int ParmSize;
374 ParmSize=pobj_parameter->SetParameter(psi->name,psi->pRealParmInfo,psi->RealParmNum,psi->RealSecondParmNum);
375
376
377
378 if(psi->ReturnType==DEF_OBJECT){
379 //////////////////////////////////////////////////////
380 // 戻り値にオブジェクト インスタンスを持つ場合
381 // ※ByRef _System_ReturnObject パラメータをセット
382 //////////////////////////////////////////////////////
383
384 int object_size;
385 object_size=GetSizeOfClass(psi->u.Return_pobj_c);
386
387 //push object_size
388 op_push_value(object_size);
389
390 //call calloc
391 extern SUBINFO *pSub_calloc;
392 op_call(pSub_calloc);
393
394 //push eax
395 op_push(REG_EAX);
396 }
397
398
399 if(psi->pobj_ParentClass&&bStatic==0){
400 //////////////////////////////////////////////////////
401 // メンバ関数の場合
402 // ※_System_LocalThis パラメータをセット
403 //////////////////////////////////////////////////////
404
405 if(ObjectName[0]){
406 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
407 else{
408 RELATIVE_VAR RelativeVar;
409 if( pMethod->isConst ){
410 //Constアクセスが可能なメソッドの場合
411 if( !GetVarOffsetReadOnly( ObjectName, &i2, &RelativeVar, 0 ) ) return;
412 }
413 else{
414 //Constアクセスが不可能なメソッドの場合
415 if( !GetVarOffsetReadWrite( ObjectName, &i2, &RelativeVar, 0 ) ) return;
416 }
417
418 SetVarPtrToEax(&RelativeVar);
419
420 //参照タイプが "->" の場合
421 if(RefType==DEF_PTR_OBJECT){
422 //mov eax,dword ptr[eax]
423 OpBuffer[obp++]=(char)0x8B;
424 OpBuffer[obp++]=(char)0x00;
425 }
426
427 //mov ecx,eax
428 OpBuffer[obp++]=(char)0x8B;
429 OpBuffer[obp++]=(char)0xC8;
430 }
431 }
432 else{
433InClassMember:
434 if(dwFlags&PROCFLAG_NEW){
435 //New演算子によるコンストラクタ呼び出しの場合
436 //mov ecx,dword ptr[esp+ParmSize]
437 OpBuffer[obp++]=(char)0x8B;
438 OpBuffer[obp++]=(char)0x8C;
439 OpBuffer[obp++]=(char)0x24;
440 *((long *)(OpBuffer+obp))=ParmSize;
441 obp+=sizeof(long);
442 }
443 else{
444 //Thisポインタをecxにコピー
445 SetThisPtrToReg(REG_ECX);
446 }
447 }
448
449 //push ecx
450 op_push(REG_ECX);
451 }
452
453 if(psi->bVirtual){
454 //仮想関数(オブジェクトメソッド)呼び出し
455 //pObj->func_table->func1
456 // ->func2
457 // ->func3
458
459 //mov edx,dword ptr[ecx]
460 OpBuffer[obp++]=(char)0x8B;
461 OpBuffer[obp++]=(char)0x11;
462
463 for(i=0,i2=0;i<pobj_c->iMethodNum;i++){
464 if(pobj_c->ppobj_Method[i]->psi==psi) break;
465 if(pobj_c->ppobj_Method[i]->psi->bVirtual) i2++;
466 }
467
468 //call dword ptr[edx+func_index]
469 if(i2*PTR_SIZE<=0x7F){
470 OpBuffer[obp++]=(char)0xFF;
471 OpBuffer[obp++]=(char)0x52;
472 OpBuffer[obp++]=(char)(i2*PTR_SIZE);
473 }
474 else{
475 OpBuffer[obp++]=(char)0xFF;
476 OpBuffer[obp++]=(char)0x92;
477 *((long *)(OpBuffer+obp))=i2*PTR_SIZE;
478 obp+=sizeof(long);
479 }
480 }
481 else{
482 //通常呼び出し
483
484 //call ProcAddr
485 op_call(psi);
486 }
487
488 if(psi->bCdecl){
489 //add esp,ParmSize
490 op_add_esp(ParmSize);
491 }
492
493 //一時オブジェクトを破棄
494 pobj_parameter->DeleteTempParameters();
495
496 //パラメータオブジェクトを破棄
497 delete pobj_parameter;
498}
499
500int Opcode_CallDllProc(char *Parameter,DECLAREINFO *pdi,LONG_PTR *plpIndex){
501 char *temporary;
502
503 temporary=(char *)HeapAlloc(hHeap,0,lstrlen(Parameter)+1);
504
505 extern BOOL bDebugCompile;
506 extern BOOL bDebugSupportProc;
507 if(bDebugCompile&&bDebugSupportProc==0&&lstrcmp(pdi->name,"DebugBreak")!=0)
508 Call_DebugSys_SaveContext();
509
510 pdi->bUse=1;
511
512
513 ////////////////////////
514 // パラメータのセット
515 ////////////////////////
516
517 //パラメータオブジェクトを生成
518 CParameter *pobj_parameter=0;
519 pobj_parameter=new CParameter(Parameter);
520
521 //エラーチェック
522 if( !pobj_parameter->ErrorCheck(pdi->name,pdi->pParmInfo,pdi->ParmNum,pdi->ParmNum) ){
523 //パラメータにエラーがあるときは処理を終える
524 return pdi->ReturnType;
525 }
526
527 //レジスタ、スタックフレームにセット
528 int ParmSize;
529 ParmSize=pobj_parameter->SetParameter(pdi->name,pdi->pParmInfo,pdi->ParmNum,pdi->ParmNum);
530
531 //パラメータオブジェクトを破棄
532 delete pobj_parameter;
533
534
535 //動的リンクされたプロシージャの呼び出し
536
537 //call dword ptr[LookupTable]
538 OpBuffer[obp++]=(char)0xFF;
539 OpBuffer[obp++]=(char)0x15;
540 pobj_ImportAddrSchedule->add(pdi);
541 obp+=sizeof(long);
542
543 if(pdi->bCdecl){
544 //add esp,ParmSize
545 op_add_esp(ParmSize);
546 }
547
548 if(plpIndex) *plpIndex=pdi->u.ReturnIndex;
549
550 HeapDefaultFree(temporary);
551
552 return pdi->ReturnType;
553}
Note: See TracBrowser for help on using the repository browser.