source: dev/BasicCompiler32/Compile_CallProc.cpp@ 47

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

列挙子の比較演算が正常に行えないバグを修正。
クラス名と同名のグローバル関数を定義できないバグを修正

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