source: dev/BasicCompiler32/Compile_Func.cpp@ 104

Last change on this file since 104 was 97, checked in by dai_9181, 18 years ago

関数の戻り値オブジェクトのメンバ・メソッドを一時オブジェクトを介さずに参照できるようにした。

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