source: dev/BasicCompiler32/Compile_Func.cpp@ 110

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

VarPtrにオブジェクトを指定したときに警告を出すようにした。(ObjPtrへの移行処理期間中のみの対応)。
バージョン情報にrev231を刻印。

File size: 12.7 KB
RevLine 
[3]1#include "../BasicCompiler_Common/common.h"
2#include "Opcode.h"
3
4int GetFunctionType(int FuncNum){
5 switch(FuncNum){
6 case FUNC_CUDBL:
7 return DEF_DOUBLE;
8 case FUNC_FIX:
9 case FUNC_LEN:
10 return DEF_LONG;
11 case FUNC_ADDRESSOF:
12 case FUNC_SIZEOF:
13 case FUNC_VARPTR:
[109]14 case FUNC_OBJPTR:
[3]15 return DEF_DWORD;
16 case FUNC_GETDOUBLE:
17 return DEF_DOUBLE;
18 case FUNC_GETSINGLE:
19 return DEF_SINGLE;
20 case FUNC_GETQWORD:
21 return DEF_QWORD;
22 case FUNC_GETDWORD:
23 return DEF_DWORD;
24 case FUNC_GETWORD:
25 return DEF_WORD;
26 case FUNC_GETBYTE:
27 return DEF_BYTE;
28 }
29 return 0;
30}
31int GetFunctionFromName(char *FuncName){
32 if(lstrcmpi(FuncName,"CUDbl")==0) return FUNC_CUDBL;
33 if(lstrcmpi(FuncName,"Fix")==0) return FUNC_FIX;
34 if(lstrcmpi(FuncName,"Len")==0) return FUNC_LEN;
35 if(lstrcmpi(FuncName,"AddressOf")==0) return FUNC_ADDRESSOF;
36 if(lstrcmpi(FuncName,"SizeOf")==0) return FUNC_SIZEOF;
37 if(lstrcmpi(FuncName,"VarPtr")==0) return FUNC_VARPTR;
[109]38 if(lstrcmpi(FuncName,"ObjPtr")==0) return FUNC_OBJPTR;
[3]39 if(lstrcmpi(FuncName,"GetDouble")==0) return FUNC_GETDOUBLE;
40 if(lstrcmpi(FuncName,"GetSingle")==0) return FUNC_GETSINGLE;
41 if(lstrcmpi(FuncName,"GetQWord")==0) return FUNC_GETQWORD;
42 if(lstrcmpi(FuncName,"GetDWord")==0) return FUNC_GETDWORD;
43 if(lstrcmpi(FuncName,"GetWord")==0) return FUNC_GETWORD;
44 if(lstrcmpi(FuncName,"GetByte")==0) return FUNC_GETBYTE;
45 return 0;
46}
47
[76]48void Opcode_Func_Fix(const char *lpszParms){
49 Type resultType;
50 if( !NumOpe( lpszParms, Type(), resultType ) ){
51 return;
52 }
[3]53
[76]54 if( resultType.IsDouble() ){
[3]55 //fld qword ptr[esp]
56 op_fld_ptr_esp(DEF_DOUBLE);
57
58 //fnstcw word ptr[esp]
59 OpBuffer[obp++]=(char)0xD9;
60 OpBuffer[obp++]=(char)0x3C;
61 OpBuffer[obp++]=(char)0x24;
62
63 //mov ax,word ptr[esp]
64 OpBuffer[obp++]=(char)0x66;
65 OpBuffer[obp++]=(char)0x8B;
66 OpBuffer[obp++]=(char)0x04;
67 OpBuffer[obp++]=(char)0x24;
68
69 //or ah,0Ch
70 OpBuffer[obp++]=(char)0x80;
71 OpBuffer[obp++]=(char)0xCC;
72 OpBuffer[obp++]=(char)0x0C;
73
74 //mov word ptr[esp-2],ax
75 OpBuffer[obp++]=(char)0x66;
76 OpBuffer[obp++]=(char)0x89;
77 OpBuffer[obp++]=(char)0x44;
78 OpBuffer[obp++]=(char)0x24;
79 OpBuffer[obp++]=(char)0xFE;
80
81 //fldcw word ptr[esp-2]
82 OpBuffer[obp++]=(char)0xD9;
83 OpBuffer[obp++]=(char)0x6C;
84 OpBuffer[obp++]=(char)0x24;
85 OpBuffer[obp++]=(char)0xFE;
86
87 //fistp dword ptr[esp+4]
88 OpBuffer[obp++]=(char)0xDB;
89 OpBuffer[obp++]=(char)0x5C;
90 OpBuffer[obp++]=(char)0x24;
91 OpBuffer[obp++]=(char)0x04;
92
93 //fldcw word ptr[esp]
94 OpBuffer[obp++]=(char)0xD9;
95 OpBuffer[obp++]=(char)0x2C;
96 OpBuffer[obp++]=(char)0x24;
97
98 //add esp,4
99 op_add_esp(4);
100 }
[76]101 else if( resultType.IsSingle() ){
[3]102 //fld dword ptr[esp]
103 op_fld_ptr_esp(DEF_SINGLE);
104
105 //sub esp,4
106 op_sub_esp(4);
107
108 //fnstcw word ptr[esp]
109 OpBuffer[obp++]=(char)0xD9;
110 OpBuffer[obp++]=(char)0x3C;
111 OpBuffer[obp++]=(char)0x24;
112
113 //mov ax,word ptr[esp]
114 OpBuffer[obp++]=(char)0x66;
115 OpBuffer[obp++]=(char)0x8B;
116 OpBuffer[obp++]=(char)0x04;
117 OpBuffer[obp++]=(char)0x24;
118
119 //or ah,0Ch
120 OpBuffer[obp++]=(char)0x80;
121 OpBuffer[obp++]=(char)0xCC;
122 OpBuffer[obp++]=(char)0x0C;
123
124 //mov word ptr[esp-2],ax
125 OpBuffer[obp++]=(char)0x66;
126 OpBuffer[obp++]=(char)0x89;
127 OpBuffer[obp++]=(char)0x44;
128 OpBuffer[obp++]=(char)0x24;
129 OpBuffer[obp++]=(char)0xFE;
130
131 //fldcw word ptr[esp-2]
132 OpBuffer[obp++]=(char)0xD9;
133 OpBuffer[obp++]=(char)0x6C;
134 OpBuffer[obp++]=(char)0x24;
135 OpBuffer[obp++]=(char)0xFE;
136
137 //fistp dword ptr[esp+4]
138 OpBuffer[obp++]=(char)0xDB;
139 OpBuffer[obp++]=(char)0x5C;
140 OpBuffer[obp++]=(char)0x24;
141 OpBuffer[obp++]=(char)0x04;
142
143 //fldcw word ptr[esp]
144 OpBuffer[obp++]=(char)0xD9;
145 OpBuffer[obp++]=(char)0x2C;
146 OpBuffer[obp++]=(char)0x24;
147
148 //add esp,4
149 op_add_esp(4);
150 }
[76]151 else if( resultType.Is64() ){
[3]152 //pop eax
153 op_pop(REG_EAX);
154
155 //add esp,4
156 op_add_esp(4);
157
158 //push eax
159 op_push(REG_EAX);
160 }
161
162 //pop eax
163 op_pop(REG_EAX);
164}
165
[46]166void Opcode_Func_CUDbl(const char *Parameter){
[76]167 Type resultType;
168 if( !NumOpe(Parameter,Type(),resultType) ){
169 return;
170 }
171 ChangeTypeToLong(resultType.GetBasicType());
[3]172
173 //pop eax
174 op_pop(REG_EAX);
175
176 //push 0
177 OpBuffer[obp++]=(char)0x6A;
178 OpBuffer[obp++]=(char)0x00;
179
180 //push eax
181 op_push(REG_EAX);
182
183 //fild qword ptr[esp]
184 OpBuffer[obp++]=(char)0xDF;
185 OpBuffer[obp++]=(char)0x2C;
186 OpBuffer[obp++]=(char)0x24;
187
188 //add esp,8
189 op_add_esp(8);
190}
[46]191void Opcode_Func_Len(const char *Parameter){
[3]192 BOOL bArrayHead;
193
[46]194 const char *tempParm=Parameter;
[3]195 char temporary[VN_SIZE];
196 char temp2[32];
[76]197 Type type;
198 if( !GetVarType(Parameter,type,0) ){
[3]199 sprintf(temporary,"_System_DummyStr2=%s",Parameter);
200 OpcodeCalc(temporary);
201
202 lstrcpy(temp2,"_System_DummyStr2");
203 tempParm=temp2;
204
205 extern CClass *pobj_StringClass;
[76]206 type.SetType( DEF_OBJECT, pobj_StringClass );
[3]207 }
208
[97]209 if( type.IsStringClass() ){
[3]210 //Stringオブジェクトの場合
211 sprintf(temporary,"%s.Length",tempParm);
212
[76]213 int reg=REG_RAX;
214 NumOpe(temporary,Type(),Type());
[3]215
216 //pop eax
217 op_pop(REG_EAX);
218
219 return;
220 }
221
222 int SubScripts[MAX_ARRAYDIM];
223 RELATIVE_VAR RelativeVar;
[76]224 if(!GetVarOffsetReadOnly(tempParm,&RelativeVar,type,SubScripts)) return;
[3]225
[76]226 if(type.GetBasicType()&FLAG_PTR){
227 type.SetBasicType( type.GetBasicType() & ( ~FLAG_PTR ) );
[3]228
229 bArrayHead=1;
230 }
231 else bArrayHead=0;
232
[76]233 int typeSize = type.GetSize();
[3]234
[76]235 if(bArrayHead) typeSize*=JumpSubScripts(SubScripts);
[3]236
237 //mov eax,TypeSize
238 OpBuffer[obp++]=(char)0xB8;
[76]239 *((long *)(OpBuffer+obp))=typeSize;
[3]240 obp+=sizeof(long);
241}
[76]242void Opcode_Func_AddressOf( const char *name ){
[3]243 extern int cp;
[75]244 UserProc *pUserProc;
[3]245
246 extern LONG_PTR ProcPtr_BaseIndex;
247 if(ProcPtr_BaseIndex!=-1){
248 //左辺の型にのっとり、オーバーロードを解決
249
[75]250 std::vector<UserProc *> subs;
[50]251 GetOverloadSubHash( name, subs );
252 if( subs.size() == 0 ){
[3]253 SetError(27,name,cp);
254 return;
255 }
256
257 //オーバーロードを解決
[88]258 pUserProc=OverloadSolution(name,subs,Smoothie::Meta::procPointers[ProcPtr_BaseIndex]->Params(), Type() );
[3]259
[75]260 if(!pUserProc){
[3]261 SetError(27,name,cp);
262 return;
263 }
264 }
265 else{
[75]266 pUserProc=GetSubHash(name);
267 if(!pUserProc){
[3]268 SetError(27,name,cp);
269 return;
270 }
271 }
272
[75]273 if( pUserProc->IsVirtual() ){
[3]274 ///////////////////////////////
275 // 仮想関数の場合
276 // thisポインタをrcxにコピー
277 ///////////////////////////////
278
279 CClass *pobj_c;
280
281 char ObjectName[VN_SIZE];
282 int RefType;
[28]283 SplitObjectName(name,ObjectName,&RefType);
[3]284
285 if(ObjectName[0]){
286 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
287 else{
288 RELATIVE_VAR RelativeVar;
[76]289 Type type;
290 if(!GetVarOffsetReadOnly(ObjectName,&RelativeVar,type)) return;
[3]291 SetVarPtrToEax(&RelativeVar);
292
293 //mov ecx,eax
294 op_mov_RR(REG_ECX,REG_EAX);
295
296 //参照タイプが整合しているかをチェック
[76]297 if(type.GetBasicType()!=RefType) SetError(104,ObjectName,cp);
[3]298
[76]299 if(type.IsObjectPtr()){
[3]300 //mov ecx,dword ptr[ecx]
301 op_mov_RM(sizeof(long),REG_ECX,REG_ECX,0,MOD_BASE);
302 }
303 }
304 }
305 else{
306InClassMember:
307 //自身のオブジェクトのThisポインタをrcxにコピー
308 SetThisPtrToReg(REG_RCX);
309
310 pobj_c=pobj_CompilingClass;
311 }
312
313
314 //仮想関数(オブジェクトメソッド)
315 //pObj->func_table->func1
316 // ->func2
317 // ->func3
318
319 //mov edx,dword ptr[ecx]
320 OpBuffer[obp++]=(char)0x8B;
321 OpBuffer[obp++]=(char)0x11;
322
[75]323 int i2 = pobj_c->GetFuncNumInVtbl( pUserProc );
[3]324
325 //mov eax,dword ptr[edx+func_index]
326 if(i2*PTR_SIZE<=0x7F){
327 op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP8);
328 }
329 else{
330 op_mov_RM(sizeof(long),REG_EAX,REG_EDX,i2*PTR_SIZE,MOD_BASE_DISP32);
331 }
332 }
333 else{
334 //一般の関数
335
336 //mov eax,ProcAddr
337 OpBuffer[obp++]=(char)0xB8;
[75]338 pobj_SubAddrSchedule->add(pUserProc,0);
[3]339 obp+=sizeof(long);
340 }
341
[75]342 pUserProc->Using();
[3]343}
[79]344void Opcode_Func_SizeOf( const string &typeName ){
345 Type tempType;
346 if( !Type::StringToType( typeName, tempType ) ){
347 SetError(3,typeName,cp);
348 return;
[3]349 }
350
[79]351 int typeSize = ( tempType.IsObject() ) ?
352 tempType.GetClass().GetSize() : tempType.GetSize();
353
[3]354 //mov eax,size
[79]355 op_mov_RV( REG_EAX, typeSize );
[3]356}
[76]357void Opcode_Func_VarPtr( const char *Parameter, Type &resultType, bool isCallOn ){
358 if( isCallOn == false ){
359 // 戻り値の型を取得するだけ
360
361 //変数のアドレスを取得
362 if(!GetVarType( Parameter, resultType, true )) return;
363
364 resultType.PtrLevelUp();
365
366 return;
367 }
368
[3]369 RELATIVE_VAR RelativeVar;
370
371 //変数のアドレスを取得
[76]372 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
[3]373
[76]374 int beforeType = resultType.GetBasicType();
[64]375
[76]376 resultType.PtrLevelUp();
[46]377
[3]378 SetVarPtrToEax(&RelativeVar);
[64]379
[109]380 // TODO: 取り除く(この動きはObjPtrに託す)
[64]381 if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){
382 //参照をオブジェクトポインタに変更
383
384 //mov eax,dword ptr[eax]
385 op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE );
[110]386
387 SetError(-120,NULL,cp);
[64]388 }
[3]389}
[109]390void Opcode_Func_ObjPtr( const char *Parameter, Type &resultType, bool isCallOn ){
391 if( isCallOn == false ){
392 // 戻り値の型を取得するだけ
393
394 //変数のアドレスを取得
395 if(!GetVarType( Parameter, resultType, true )) return;
396
397 resultType.PtrLevelUp();
398
399 return;
400 }
401
402 RELATIVE_VAR RelativeVar;
403
404 //変数のアドレスを取得
405 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
406
407 int beforeType = resultType.GetBasicType();
408
409 resultType.PtrLevelUp();
410
411 SetVarPtrToEax(&RelativeVar);
412
413 if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){
414 //参照をオブジェクトポインタに変更
415
416 //mov eax,dword ptr[eax]
417 op_mov_RM( sizeof(long), REG_EAX, REG_EAX, 0, MOD_BASE );
418 }
419 else{
420 SetError(134,NULL,cp );
421 }
422}
[46]423void Opcode_Func_GetPtrData(const char *Parameter,const int type){
[76]424 Type tempType;
425 if( !NumOpe(Parameter,Type(),tempType) ){
426 return;
427 }
428 if(!tempType.IsWhole()){
429 SetError(11,Parameter,cp);
430 return;
431 }
432 ChangeTypeToLong(tempType.GetBasicType());
[3]433
434 if(type==DEF_DOUBLE){
435 //pop eax
436 op_pop(REG_EAX);
437
438 //fld qword ptr[eax]
439 OpBuffer[obp++]=(char)0xDD;
440 OpBuffer[obp++]=(char)0x00;
441 }
442 else if(type==DEF_SINGLE||type==DEF_DWORD){
443 //pop eax
444 op_pop(REG_EAX);
445
446 //mov eax,dword ptr[eax]
447 OpBuffer[obp++]=(char)0x8B;
448 OpBuffer[obp++]=(char)0x00;
449 }
450 else if(type==DEF_QWORD){
451 //pop ecx
452 op_pop(REG_ECX);
453
454 //mov eax,dword ptr[ecx]
455 op_mov_RM(sizeof(long),REG_EAX,REG_ECX,0,MOD_BASE);
456
457 //mov edx,dword ptr[ecx+sizeof(long)]
458 op_mov_RM(sizeof(long),REG_EDX,REG_ECX,sizeof(long),MOD_BASE_DISP8);
459 }
460 else if(type==DEF_WORD){
461 //pop ebx
462 op_pop(REG_EBX);
463
464 //xor eax,eax
465 OpBuffer[obp++]=(char)0x33;
466 OpBuffer[obp++]=(char)0xC0;
467
468 //mov ax,word ptr[ebx]
469 OpBuffer[obp++]=(char)0x66;
470 OpBuffer[obp++]=(char)0x8B;
471 OpBuffer[obp++]=(char)0x03;
472 }
473 else if(type==DEF_BYTE){
474 //pop ebx
475 op_pop(REG_EBX);
476
477 //xor eax,eax
478 OpBuffer[obp++]=(char)0x33;
479 OpBuffer[obp++]=(char)0xC0;
480
481 //mov al,byte ptr[ebx]
482 OpBuffer[obp++]=(char)0x8A;
483 OpBuffer[obp++]=(char)0x03;
484 }
485}
486
[76]487bool Opcode_CallFunc( const char *Parameter, const int FuncNum, Type &resultType, bool isCallOn ){
[3]488 switch(FuncNum){
489 case FUNC_FIX:
[76]490 if( isCallOn ) Opcode_Func_Fix(Parameter);
491 resultType.SetBasicType( DEF_LONG );
[46]492 break;
[3]493 case FUNC_CUDBL:
[76]494 if( isCallOn ) Opcode_Func_CUDbl(Parameter);
495 resultType.SetBasicType( DEF_DOUBLE );
[46]496 break;
[3]497 case FUNC_LEN:
[76]498 if( isCallOn ) Opcode_Func_Len(Parameter);
499 resultType.SetBasicType( DEF_LONG );
[46]500 break;
[3]501 case FUNC_ADDRESSOF:
[76]502 if( isCallOn ) Opcode_Func_AddressOf(Parameter);
503 resultType.SetBasicType( DEF_PTR_VOID );
[46]504 break;
[3]505 case FUNC_SIZEOF:
[76]506 if( isCallOn ) Opcode_Func_SizeOf(Parameter);
507 resultType.SetBasicType( DEF_LONG );
[46]508 break;
[3]509 case FUNC_VARPTR:
[76]510 Opcode_Func_VarPtr( Parameter, resultType, isCallOn );
[46]511 break;
[109]512 case FUNC_OBJPTR:
513 Opcode_Func_ObjPtr( Parameter, resultType, isCallOn );
514 break;
[3]515
516 case FUNC_GETDOUBLE:
[76]517 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DOUBLE);
518 resultType.SetBasicType( DEF_DOUBLE );
[46]519 break;
[3]520 case FUNC_GETSINGLE:
[76]521 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_SINGLE);
522 resultType.SetBasicType( DEF_SINGLE );
[46]523 break;
[3]524 case FUNC_GETQWORD:
[76]525 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_QWORD);
526 resultType.SetBasicType( DEF_QWORD );
[46]527 break;
[3]528 case FUNC_GETDWORD:
[76]529 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DWORD);
530 resultType.SetBasicType( DEF_DWORD );
[46]531 break;
[3]532 case FUNC_GETWORD:
[76]533 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_WORD);
534 resultType.SetBasicType( DEF_WORD );
[46]535 break;
[3]536 case FUNC_GETBYTE:
[76]537 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_BYTE);
538 resultType.SetBasicType( DEF_BYTE );
[46]539 break;
[76]540 default:
541 return false;
[3]542 }
[76]543 return true;
[3]544}
Note: See TracBrowser for help on using the repository browser.