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

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