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
Line 
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:
14 case FUNC_OBJPTR:
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;
38 if(lstrcmpi(FuncName,"ObjPtr")==0) return FUNC_OBJPTR;
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
48void Opcode_Func_Fix(const char *lpszParms){
49 Type resultType;
50 if( !NumOpe( lpszParms, Type(), resultType ) ){
51 return;
52 }
53
54 if( resultType.IsDouble() ){
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 }
101 else if( resultType.IsSingle() ){
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 }
151 else if( resultType.Is64() ){
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
166void Opcode_Func_CUDbl(const char *Parameter){
167 Type resultType;
168 if( !NumOpe(Parameter,Type(),resultType) ){
169 return;
170 }
171 ChangeTypeToLong(resultType.GetBasicType());
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}
191void Opcode_Func_Len(const char *Parameter){
192 BOOL bArrayHead;
193
194 const char *tempParm=Parameter;
195 char temporary[VN_SIZE];
196 char temp2[32];
197 Type type;
198 if( !GetVarType(Parameter,type,0) ){
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;
206 type.SetType( DEF_OBJECT, pobj_StringClass );
207 }
208
209 if( type.IsStringClass() ){
210 //Stringオブジェクトの場合
211 sprintf(temporary,"%s.Length",tempParm);
212
213 int reg=REG_RAX;
214 NumOpe(temporary,Type(),Type());
215
216 //pop eax
217 op_pop(REG_EAX);
218
219 return;
220 }
221
222 int SubScripts[MAX_ARRAYDIM];
223 RELATIVE_VAR RelativeVar;
224 if(!GetVarOffsetReadOnly(tempParm,&RelativeVar,type,SubScripts)) return;
225
226 if(type.GetBasicType()&FLAG_PTR){
227 type.SetBasicType( type.GetBasicType() & ( ~FLAG_PTR ) );
228
229 bArrayHead=1;
230 }
231 else bArrayHead=0;
232
233 int typeSize = type.GetSize();
234
235 if(bArrayHead) typeSize*=JumpSubScripts(SubScripts);
236
237 //mov eax,TypeSize
238 OpBuffer[obp++]=(char)0xB8;
239 *((long *)(OpBuffer+obp))=typeSize;
240 obp+=sizeof(long);
241}
242void Opcode_Func_AddressOf( const char *name ){
243 extern int cp;
244 UserProc *pUserProc;
245
246 extern LONG_PTR ProcPtr_BaseIndex;
247 if(ProcPtr_BaseIndex!=-1){
248 //左辺の型にのっとり、オーバーロードを解決
249
250 std::vector<UserProc *> subs;
251 GetOverloadSubHash( name, subs );
252 if( subs.size() == 0 ){
253 SetError(27,name,cp);
254 return;
255 }
256
257 //オーバーロードを解決
258 pUserProc=OverloadSolution(name,subs,Smoothie::Meta::procPointers[ProcPtr_BaseIndex]->Params(), Type() );
259
260 if(!pUserProc){
261 SetError(27,name,cp);
262 return;
263 }
264 }
265 else{
266 pUserProc=GetSubHash(name);
267 if(!pUserProc){
268 SetError(27,name,cp);
269 return;
270 }
271 }
272
273 if( pUserProc->IsVirtual() ){
274 ///////////////////////////////
275 // 仮想関数の場合
276 // thisポインタをrcxにコピー
277 ///////////////////////////////
278
279 CClass *pobj_c;
280
281 char ObjectName[VN_SIZE];
282 int RefType;
283 SplitObjectName(name,ObjectName,&RefType);
284
285 if(ObjectName[0]){
286 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
287 else{
288 RELATIVE_VAR RelativeVar;
289 Type type;
290 if(!GetVarOffsetReadOnly(ObjectName,&RelativeVar,type)) return;
291 SetVarPtrToEax(&RelativeVar);
292
293 //mov ecx,eax
294 op_mov_RR(REG_ECX,REG_EAX);
295
296 //参照タイプが整合しているかをチェック
297 if(type.GetBasicType()!=RefType) SetError(104,ObjectName,cp);
298
299 if(type.IsObjectPtr()){
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
323 int i2 = pobj_c->GetFuncNumInVtbl( pUserProc );
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;
338 pobj_SubAddrSchedule->add(pUserProc,0);
339 obp+=sizeof(long);
340 }
341
342 pUserProc->Using();
343}
344void Opcode_Func_SizeOf( const string &typeName ){
345 Type tempType;
346 if( !Type::StringToType( typeName, tempType ) ){
347 SetError(3,typeName,cp);
348 return;
349 }
350
351 int typeSize = ( tempType.IsObject() ) ?
352 tempType.GetClass().GetSize() : tempType.GetSize();
353
354 //mov eax,size
355 op_mov_RV( REG_EAX, typeSize );
356}
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
369 RELATIVE_VAR RelativeVar;
370
371 //変数のアドレスを取得
372 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
373
374 int beforeType = resultType.GetBasicType();
375
376 resultType.PtrLevelUp();
377
378 SetVarPtrToEax(&RelativeVar);
379
380 // TODO: 取り除く(この動きはObjPtrに託す)
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 );
386
387 SetError(-120,NULL,cp);
388 }
389}
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}
423void Opcode_Func_GetPtrData(const char *Parameter,const int type){
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());
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
487bool Opcode_CallFunc( const char *Parameter, const int FuncNum, Type &resultType, bool isCallOn ){
488 switch(FuncNum){
489 case FUNC_FIX:
490 if( isCallOn ) Opcode_Func_Fix(Parameter);
491 resultType.SetBasicType( DEF_LONG );
492 break;
493 case FUNC_CUDBL:
494 if( isCallOn ) Opcode_Func_CUDbl(Parameter);
495 resultType.SetBasicType( DEF_DOUBLE );
496 break;
497 case FUNC_LEN:
498 if( isCallOn ) Opcode_Func_Len(Parameter);
499 resultType.SetBasicType( DEF_LONG );
500 break;
501 case FUNC_ADDRESSOF:
502 if( isCallOn ) Opcode_Func_AddressOf(Parameter);
503 resultType.SetBasicType( DEF_PTR_VOID );
504 break;
505 case FUNC_SIZEOF:
506 if( isCallOn ) Opcode_Func_SizeOf(Parameter);
507 resultType.SetBasicType( DEF_LONG );
508 break;
509 case FUNC_VARPTR:
510 Opcode_Func_VarPtr( Parameter, resultType, isCallOn );
511 break;
512 case FUNC_OBJPTR:
513 Opcode_Func_ObjPtr( Parameter, resultType, isCallOn );
514 break;
515
516 case FUNC_GETDOUBLE:
517 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DOUBLE);
518 resultType.SetBasicType( DEF_DOUBLE );
519 break;
520 case FUNC_GETSINGLE:
521 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_SINGLE);
522 resultType.SetBasicType( DEF_SINGLE );
523 break;
524 case FUNC_GETQWORD:
525 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_QWORD);
526 resultType.SetBasicType( DEF_QWORD );
527 break;
528 case FUNC_GETDWORD:
529 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DWORD);
530 resultType.SetBasicType( DEF_DWORD );
531 break;
532 case FUNC_GETWORD:
533 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_WORD);
534 resultType.SetBasicType( DEF_WORD );
535 break;
536 case FUNC_GETBYTE:
537 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_BYTE);
538 resultType.SetBasicType( DEF_BYTE );
539 break;
540 default:
541 return false;
542 }
543 return true;
544}
Note: See TracBrowser for help on using the repository browser.