source: dev/trunk/abdev/BasicCompiler32/Compile_CallProc.cpp@ 183

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