source: dev/BasicCompiler32/Compile_CallProc.cpp@ 20

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

参照型パラメータに関数の戻り値オブジェクトを指定した場合などの、一時オブジェクトの扱いを可能にした。
Dimで指定される初期値を見分けることで、As指定を省略できるようにした。

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