source: dev/trunk/abdev/BasicCompiler64/Compile_Func.cpp@ 357

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

例外処理機構実装中...

File size: 14.7 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4
5#include <Compiler.h>
6
7#include "../BasicCompiler_Common/common.h"
8#include "Opcode.h"
9
10int GetFunctionFromName(char *FuncName){
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, "__delegate_dynamicmethod_call" ) == 0 ) return FUNC_DELEGATE_DYNAMICMETHOD_CALL;
17 if( lstrcmpi( FuncName, "__delegate_staticmethod_call" ) == 0 ) return FUNC_DELEGATE_STATICMETHOD_CALL;
18 if( lstrcmpi( FuncName, "_System_GetNowScopeCatchAddresses" ) == 0 )return FUNC_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS;
19 if( lstrcmpi( FuncName, "GetDouble" ) == 0 ) return FUNC_GETDOUBLE;
20 if( lstrcmpi( FuncName, "GetSingle" ) == 0 ) return FUNC_GETSINGLE;
21 if( lstrcmpi( FuncName, "GetQWord" ) == 0 ) return FUNC_GETQWORD;
22 if( lstrcmpi( FuncName, "GetDWord" ) == 0 ) return FUNC_GETDWORD;
23 if( lstrcmpi( FuncName, "GetWord" ) == 0 ) return FUNC_GETWORD;
24 if( lstrcmpi( FuncName, "GetByte" ) == 0 ) return FUNC_GETBYTE;
25 return 0;
26}
27void Opcode_Func_Len( const char *Parameter ){
28 BOOL bArrayHead;
29
30 const char *tempParm=Parameter;
31 char temporary[VN_SIZE];
32 char temp2[32];
33 Type type;
34 if( !GetVarType(Parameter,type,0) ){
35 sprintf(temporary,"_System_DummyStr2=%s",Parameter);
36 OpcodeCalc(temporary);
37
38 lstrcpy(temp2,"_System_DummyStr2");
39 tempParm=temp2;
40
41 type.SetType( DEF_OBJECT, compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr() );
42 }
43
44 if( type.IsStringClass() ){
45 //Stringオブジェクトの場合
46 sprintf(temporary,"%s.Length",tempParm);
47
48 int reg=REG_RAX;
49 NumOpe(&reg,temporary,Type(),Type());
50 return;
51 }
52
53 Subscripts subscripts;
54 RELATIVE_VAR RelativeVar;
55 if(!GetVarOffsetReadOnly(tempParm,&RelativeVar,type,&subscripts)) return;
56
57 if(type.GetBasicType()&FLAG_PTR){
58 type.SetBasicType( type.GetBasicType() & ( ~FLAG_PTR ) );
59
60 bArrayHead=1;
61 }
62 else bArrayHead=0;
63
64 int typeSize = type.GetSize();
65
66 if(bArrayHead) typeSize*=JumpSubScripts(subscripts);
67
68 //mov rax,TypeSize
69 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,typeSize);
70
71 return;
72}
73
74void _Opcode_Func_AddressOf( const char *methodInstanceName, const UserProc &userProc )
75{
76 if( userProc.IsVirtual() )
77 {
78 ///////////////////////////////
79 // 仮想関数の場合
80 // thisポインタをrcxにコピー
81 ///////////////////////////////
82
83 const CClass *pobj_c;
84
85 char ObjectName[VN_SIZE];
86 ReferenceKind referenceKind;
87 SplitObjectName(methodInstanceName,ObjectName, referenceKind );
88
89 if(ObjectName[0]){
90 if(lstrcmpi(ObjectName,"Super")==0) goto InClassMember;
91 else{
92 RELATIVE_VAR RelativeVar;
93 Type type;
94 if(!GetVarOffsetReadOnly(ObjectName,&RelativeVar,type)) return;
95 SetVarPtrToReg(REG_RCX,&RelativeVar);
96
97 //参照タイプが整合しているかをチェック
98 if( !( type.IsObject() && referenceKind == RefDot
99 || type.IsObjectPtr() && referenceKind == RefPointer ) )
100 {
101 SetError(104,ObjectName,cp);
102 }
103
104 if(type.IsObjectPtr()){
105 //mov rcx,qword ptr[rcx]
106 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,0,MOD_BASE);
107 }
108 }
109 }
110 else{
111InClassMember:
112 //自身のオブジェクトのThisポインタをrcxにコピー
113 SetThisPtrToReg(REG_RCX);
114
115 pobj_c=compiler.pCompilingClass;
116 }
117
118
119 int vtblIndex;
120 if( pobj_c->IsInterface() )
121 {
122 // インターフェイスメソッド
123
124 int offset_vtbl = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__vtbl" );
125
126 // vtblのポインタを取得
127 //mov r11,qword ptr[rcx+offset_vtbl]
128 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,offset_vtbl,MOD_BASE_DISP8);
129
130 int offset_this = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr()->GetMemberOffset( "__this" );
131
132 // インターフェイスの場合は更に__thisを取得する
133 //mov rcx,qword ptr[rcx+offset_this]
134 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RCX,offset_this,MOD_BASE_DISP8);
135
136 int vtblMasterListIndex;
137 pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex );
138 if( vtblMasterListIndex != 0 )
139 {
140 SetError();
141 }
142 }
143 else
144 {
145 //仮想関数(オブジェクトメソッド)
146 // pObj -> vtbl_master_list -> vtbl1 -> func1
147 // -> func2
148 // -> func3
149 // -> vtbl2 -> func1
150 // -> func2
151 // -> func3
152
153 int vtblMasterListIndex;
154 pobj_c->GetVtblMasterListIndexAndVtblIndex( &userProc, vtblMasterListIndex, vtblIndex );
155
156 // vtblマスターリストのポインタを取得
157 //mov r11,qword ptr[rcx]
158 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RCX,0,MOD_BASE);
159
160 // vtblのポインタを取得
161 //mov r11,dword ptr[r11+vtblMasterListIndex]
162 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_R11, REG_R11, vtblMasterListIndex, MOD_BASE_DISP32 );
163 }
164
165 //mov rax,qword ptr[r11+func_index]
166 if( vtblIndex * PTR_SIZE <= 0x7F )
167 {
168 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP8);
169 }
170 else
171 {
172 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RAX,REG_R11,vtblIndex*PTR_SIZE,MOD_BASE_DISP32);
173 }
174 }
175 else{
176 //一般の関数
177
178 //mov rax,ProcAddr
179 compiler.codeGenerator.op_addressof( REG_RAX, &userProc );
180 }
181
182 userProc.Using();
183}
184void Opcode_CreateDelegate( const CClass &dgClass, const char *methodInstanceName, const UserProc &userProc )
185{
186 /////////////////////////////////////////////////////////////////
187 // 関数ポインタをpush
188 /////////////////////////////////////////////////////////////////
189
190 //mov rax,AddressOf
191 _Opcode_Func_AddressOf( methodInstanceName, userProc );
192
193
194 if( userProc.GetMethod().IsDynamic() )
195 {
196 //mov rdx,rax
197 compiler.codeGenerator.op_mov_RR( REG_RDX, REG_RAX );
198
199 pobj_BlockReg->lock( REG_RDX );
200
201
202 /////////////////////////////////////////////////////////////////
203 // オブジェクト ポインタをpush
204 /////////////////////////////////////////////////////////////////
205
206 // オブジェクト名を取得
207 char objectName[VN_SIZE];
208 char memberName[VN_SIZE];
209 char *thisPtrName = "This";
210 Type type;
211 if( SplitMemberName( methodInstanceName, objectName, memberName ) )
212 {
213 if( GetVarType( objectName, type, false ) )
214 {
215 thisPtrName = objectName;
216 }
217 }
218
219 // オブジェクト ポインタを取得
220 RELATIVE_VAR relativeVar;
221 GetVarOffsetReadOnly( thisPtrName, &relativeVar, type );
222 if( !type.IsObject() )
223 {
224 extern int cp;
225 SetError(1,NULL,cp);
226 return;
227 }
228
229 SetVarPtrToReg( REG_RAX, &relativeVar );
230
231 //mov rcx,dword ptr[rax]
232 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RCX, REG_RAX, 0, MOD_BASE );
233
234 pobj_BlockReg->unlock( REG_RDX );
235 }
236 else
237 {
238 //mov rcx,rax
239 compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX );
240 }
241
242
243 /////////////////////////////////////////////////////////////////
244 // call _CreateDynamicDelegate/_CreateStaticDelegate
245 /////////////////////////////////////////////////////////////////
246
247 std::vector<const UserProc *> subs;
248 if( userProc.GetMethod().IsDynamic() )
249 {
250 dgClass.GetStaticMethods().Enum( "_CreateDynamicDelegate", subs );
251 }
252 else
253 {
254 dgClass.GetStaticMethods().Enum( "_CreateStaticDelegate", subs );
255 }
256
257 // call _CreateDynamicDelegate
258 compiler.codeGenerator.op_call( subs[0] );
259}
260void Opcode_Func_AddressOf( const char *name, const Type &baseType, bool isCallOn, Type &resultType )
261{
262 extern int cp;
263 const UserProc *pUserProc;
264
265 const Parameters *pBaseParams = NULL;
266 if( baseType.IsProcPtr() )
267 {
268 // 左辺で関数ポインタを要求されているとき
269 pBaseParams = &compiler.GetObjectModule().meta.GetProcPointers()[baseType.GetIndex()]->Params();
270 }
271 else if( baseType.IsDelegate() )
272 {
273 // 左辺でデリゲートを要求されているとき
274 pBaseParams = &baseType.GetClass().GetDelegate().Params();
275 }
276
277 if( pBaseParams )
278 {
279 //左辺の型にのっとり、オーバーロードを解決
280
281 std::vector<const UserProc *> subs;
282 GetOverloadSubHash( name, subs );
283 if( subs.size() == 0 ){
284 SetError(27,name,cp);
285 return;
286 }
287
288 //オーバーロードを解決
289 pUserProc=OverloadSolution( name, subs, *pBaseParams, Type() );
290
291 if( isCallOn && baseType.IsDelegate() )
292 {
293 // コード生成を伴う場合はエラーチェックを行う
294 if( !pUserProc->Params().Equals( *pBaseParams )
295 || !pUserProc->ReturnType().Equals( baseType.GetClass().GetDelegate().ReturnType() ) )
296 {
297 if( baseType.IsDelegate() )
298 {
299 SetError(67, name, cp );
300 }
301 else
302 {
303 SetError(66, name, cp );
304 }
305 }
306 }
307
308 if(!pUserProc){
309 SetError(27,name,cp);
310 return;
311 }
312 }
313 else{
314 pUserProc=GetSubHash(name);
315 if(!pUserProc){
316 SetError(27,name,cp);
317 return;
318 }
319 }
320
321 if( baseType.IsDelegate() )
322 {
323 if( isCallOn )
324 {
325 // デリゲートのとき
326 Opcode_CreateDelegate( baseType.GetClass(), name, *pUserProc );
327 }
328 resultType = baseType;
329 }
330 else
331 {
332 if( isCallOn )
333 {
334 // 関数ポインタのとき
335 _Opcode_Func_AddressOf( name, *pUserProc );
336 }
337 resultType.SetBasicType( DEF_PTR_VOID );
338 }
339}
340void Opcode_Func_SizeOf( const string &typeName ){
341 Type tempType;
342 if( !compiler.StringToType( typeName, tempType ) ){
343 SetError(3,typeName,cp);
344 return;
345 }
346
347 int typeSize = ( tempType.IsObject() ) ?
348 tempType.GetClass().GetSize() : tempType.GetSize();
349
350 //mov rax,size
351 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,typeSize);
352}
353void Opcode_Func_VarPtr( const char *Parameter, Type &resultType, bool isCallOn ){
354 if( isCallOn == false ){
355 // 戻り値の型を取得するだけ
356
357 //変数のアドレスを取得
358 if(!GetVarType( Parameter, resultType, true )) return;
359
360 resultType.PtrLevelUp();
361
362 return;
363 }
364
365 RELATIVE_VAR RelativeVar;
366
367 //変数のアドレスを取得
368 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
369
370 int beforeType = resultType.GetBasicType();
371
372 resultType.PtrLevelUp();
373
374 SetVarPtrToReg(REG_RAX,&RelativeVar);
375
376 // TODO: 取り除く(この動きはObjPtrに託す)
377 /*
378 if( beforeType == DEF_OBJECT && lstrcmpi( Parameter, "This" ) != 0 ){
379 //参照をオブジェクトポインタに変更
380
381 //mov rax,qword ptr[rax]
382 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE );
383
384 SetError(-120,NULL,cp);
385 }*/
386}
387void Opcode_Func_ObjPtr( const char *Parameter, Type &resultType, bool isCallOn ){
388 if( isCallOn == false ){
389 // 戻り値の型を取得するだけ
390
391 //変数のアドレスを取得
392 if(!GetVarType( Parameter, resultType, true )) return;
393
394 resultType.PtrLevelUp();
395
396 return;
397 }
398
399 RELATIVE_VAR RelativeVar;
400
401 //変数のアドレスを取得
402 if(!GetVarOffsetReadOnly( Parameter, &RelativeVar, resultType )) return;
403
404 int beforeType = resultType.GetBasicType();
405
406 resultType.PtrLevelUp();
407
408 SetVarPtrToReg(REG_RAX,&RelativeVar);
409
410 if( lstrcmpi( Parameter, "This" )==0 ){
411 // Thisの場合は特別にオブジェクトポインタが返ってくるので、何もせずに抜ける
412 }
413 else if( beforeType == DEF_OBJECT ){
414 //参照をオブジェクトポインタに変更
415
416 //mov rax,qword ptr[rax]
417 compiler.codeGenerator.op_mov_RM( sizeof(_int64), REG_RAX, REG_RAX, 0, MOD_BASE );
418 }
419 else{
420 SetError(134,NULL,cp );
421 }
422}
423
424void Opcode_Func_delegate_call( const char *paramsStr, Type &resultType, bool isDynamicCall, bool isCallOn )
425{
426 if( isCallOn )
427 {
428 int i = 0;
429 char methodPtrParamStr[VN_SIZE];
430 i = GetOneParameter( paramsStr, i, methodPtrParamStr );
431
432 char objPtrValueStr[VN_SIZE] = "";
433 if( isDynamicCall )
434 {
435 i = GetOneParameter( paramsStr, i, objPtrValueStr );
436 }
437
438 Opcode_CallDelegate( compiler.pCompilingClass->GetDelegate(), methodPtrParamStr, objPtrValueStr, paramsStr + i );
439 }
440
441 resultType = UserProc::CompilingUserProc().ReturnType();
442}
443
444void Opcode_Func_System_Get_Bp()
445{
446 //mov rax,rbp
447 compiler.codeGenerator.op_mov_RR(REG_RAX,REG_RBP);
448}
449
450void Opcode_Func_GetPtrData( const char *Parameter, const int type ){
451 int reg=REG_RAX;
452 Type tempType;
453 if( !NumOpe(&reg,Parameter,Type(),tempType) ){
454 return;
455 }
456 if(!tempType.IsWhole()){
457 SetError(11,Parameter,cp);
458 return;
459 }
460
461 if(type==DEF_DOUBLE){
462 //movlpd xmm0,qword ptr[rax]
463 compiler.codeGenerator.op_movlpd_RM(REG_XMM0,REG_RAX,0,MOD_BASE);
464 }
465 else if(type==DEF_SINGLE){
466 //movss xmm0,dword ptr[rax]
467 compiler.codeGenerator.op_movss_RM(REG_XMM0,REG_RAX,0,MOD_BASE);
468 }
469 else{
470 //mov rax,ptr[rax]
471 compiler.codeGenerator.op_mov_RM(Type(type).GetSize(),REG_RAX,REG_RAX,0,MOD_BASE);
472 }
473}
474
475bool Opcode_CallFunc( const char *Parameter, const int FuncNum, const Type &baseType, Type &resultType, bool isCallOn )
476{
477 switch(FuncNum){
478 case FUNC_LEN:
479 if( isCallOn ) Opcode_Func_Len(Parameter);
480 resultType.SetBasicType( DEF_LONG );
481 break;
482 case FUNC_ADDRESSOF:
483 Opcode_Func_AddressOf( Parameter, baseType, isCallOn, resultType );
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 case FUNC_DELEGATE_DYNAMICMETHOD_CALL:
496 Opcode_Func_delegate_call( Parameter, resultType, true, isCallOn );
497 break;
498 case FUNC_DELEGATE_STATICMETHOD_CALL:
499 Opcode_Func_delegate_call( Parameter, resultType, false, isCallOn );
500 break;
501 case FUNC_SYSTEM_GET_NOW_SCOPE_CATCH_ADDRESS:
502 if( isCallOn ) Exception::Opcode_Func_System_GetNowScopeCatchAddress();
503 resultType.SetBasicType( DEF_LONG );
504 break;
505 case FUNC_SYSTEM_GET_BP:
506 if( isCallOn ) Opcode_Func_System_Get_Bp();
507 resultType.SetBasicType( DEF_LONG );
508 break;
509
510 case FUNC_GETDOUBLE:
511 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DOUBLE);
512 resultType.SetBasicType( DEF_DOUBLE );
513 break;
514 case FUNC_GETSINGLE:
515 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_SINGLE);
516 resultType.SetBasicType( DEF_SINGLE );
517 break;
518 case FUNC_GETQWORD:
519 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_QWORD);
520 resultType.SetBasicType( DEF_QWORD );
521 break;
522 case FUNC_GETDWORD:
523 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_DWORD);
524 resultType.SetBasicType( DEF_DWORD );
525 break;
526 case FUNC_GETWORD:
527 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_WORD);
528 resultType.SetBasicType( DEF_WORD );
529 break;
530 case FUNC_GETBYTE:
531 if( isCallOn ) Opcode_Func_GetPtrData(Parameter,DEF_BYTE);
532 resultType.SetBasicType( DEF_BYTE );
533 break;
534 default:
535 return false;
536 }
537 return true;
538}
Note: See TracBrowser for help on using the repository browser.