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

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