source: dev/trunk/abdev/BasicCompiler32/Compile_Calc.cpp@ 415

Last change on this file since 415 was 415, checked in by dai_9181, 16 years ago

代入演算時の左辺に関数呼び出しの戻り値を評価してメンバを取得するようなコードが存在するとき、エラーになってしまっていたので改修した。(32bit版のみ対応)

File size: 14.7 KB
RevLine 
[206]1#include "stdafx.h"
2
[183]3#include <jenga/include/smoothie/Smoothie.h>
4
[193]5#include <Compiler.h>
6
[3]7#include "../BasicCompiler_Common/common.h"
8#include "Opcode.h"
9
10void ChangeTypeToDouble_ToFpuReg(int OldType){
11 //現在のスタックの内容を実数レジスタに保存する
12 //NumOpeの直後専用
13 if(OldType==DEF_DOUBLE){
14 //fld qword ptr[esp]
[225]15 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
[3]16
17 //add esp,8
[225]18 compiler.codeGenerator.op_add_esp(8);
[3]19 }
20 else if(OldType==DEF_SINGLE){
21 //fld dword ptr[esp]
[225]22 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
[3]23
24 //add esp,4
[225]25 compiler.codeGenerator.op_add_esp(4);
[3]26 }
27 else if(OldType==DEF_LONG){
28 //fild dword ptr[esp]
[225]29 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
[3]30
31 //add esp,4
[225]32 compiler.codeGenerator.op_add_esp(4);
[3]33 }
34 else if(OldType==DEF_DWORD){
35 //pop eax
[225]36 compiler.codeGenerator.op_pop(REG_EAX);
[3]37
38 //push 0
[225]39 compiler.codeGenerator.op_push_V(0);
[3]40
41 //push eax
[225]42 compiler.codeGenerator.op_push(REG_EAX);
[3]43
44 //fild qword ptr[esp]
[225]45 compiler.codeGenerator.PutOld(
46 (char)0xDF,
47 (char)0x2C,
48 (char)0x24
49 );
[3]50
51 //add esp,8
[225]52 compiler.codeGenerator.op_add_esp(8);
[3]53 }
54}
55void ChangeTypeToDouble(int OldType){
56 //現在のスタックの内容をdouble型に変換する
57 //NumOpeの直後専用
58 if(OldType==DEF_DOUBLE) return;
59 else if(OldType==DEF_SINGLE){
60 //fld dword ptr[esp]
[225]61 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
[3]62
63 //sub esp,4
[225]64 compiler.codeGenerator.op_sub_esp(4);
[3]65
66 //fstp qword ptr[esp]
[225]67 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
[3]68 }
69 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
70 //64ビット整数型
71
72 //fild qword ptr[esp]
[225]73 compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64);
[3]74
75 //fstp qword ptr[esp]
[225]76 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
[3]77 }
78 else if(IsWholeNumberType(OldType)){
79 //その他整数型
80
81 if(IsSignedType(OldType)){
82 //符号あり
83
[183]84 if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){
[3]85 //pop eax
[225]86 compiler.codeGenerator.op_pop(REG_EAX);
[3]87
88 //movsx eax,ax
[225]89 compiler.codeGenerator.op_movsx_R32R16( REG_EAX );
[3]90
91 //push eax
[225]92 compiler.codeGenerator.op_push(REG_EAX);
[3]93 }
[183]94 else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){
[3]95 //pop eax
[225]96 compiler.codeGenerator.op_pop(REG_EAX);
[3]97
98 //movsx eax,al
[225]99 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
[3]100
101 //push eax
[225]102 compiler.codeGenerator.op_push(REG_EAX);
[3]103 }
104
105 //fild dword ptr[esp]
[225]106 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
[3]107
108 //sub esp,4
[225]109 compiler.codeGenerator.op_sub_esp(4);
[3]110 }
111 else{
112 //符号なし
113
114 //pop eax
[225]115 compiler.codeGenerator.op_pop(REG_EAX);
[3]116
117 //push 0
[225]118 compiler.codeGenerator.op_push_V(0);
[3]119
120 //push eax
[225]121 compiler.codeGenerator.op_push(REG_EAX);
[3]122
123 //fild qword ptr[esp]
[225]124 compiler.codeGenerator.PutOld(
125 (char)0xDF,
126 (char)0x2C,
127 (char)0x24
128 );
[3]129 }
130
131 //fstp qword ptr[esp]
[225]132 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
[3]133 }
134 else SetError(9,NULL,cp);
135}
136void ChangeTypeToSingle(int OldType){
137 //現在のスタックの内容をfloat型に変換する
138 //NumOpeの直後専用
139 if(OldType==DEF_SINGLE) return;
140 else if(OldType==DEF_DOUBLE){
141 //fld qword ptr[esp]
[225]142 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
[3]143
144 //add esp,4
[225]145 compiler.codeGenerator.op_add_esp(4);
[3]146
147 //fstp dword ptr[esp]
[225]148 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
[3]149 }
150 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
151 //64ビット整数型
152
153 //fild qword ptr[esp]
[225]154 compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64);
[3]155
156 //add esp,4
[225]157 compiler.codeGenerator.op_add_esp(4);
[3]158
159 //fstp dword ptr[esp]
[225]160 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
[3]161 }
162 else if(IsWholeNumberType(OldType)){
163 //その他整数型
164
165 if(IsSignedType(OldType)){
166 //符号あり
167
[183]168 if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){
[3]169 //pop eax
[225]170 compiler.codeGenerator.op_pop(REG_EAX);
[3]171
172 //movsx eax,ax
[225]173 compiler.codeGenerator.op_movsx_R32R16( REG_EAX );
[3]174
175 //push eax
[225]176 compiler.codeGenerator.op_push(REG_EAX);
[3]177 }
[183]178 else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){
[3]179 //pop eax
[225]180 compiler.codeGenerator.op_pop(REG_EAX);
[3]181
182 //movsx eax,al
[225]183 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
[3]184
185 //push eax
[225]186 compiler.codeGenerator.op_push(REG_EAX);
[3]187 }
188
189 //fild dword ptr[esp]
[225]190 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
[3]191 }
192 else{
193 //符号なし
194
195 //fild dword ptr[esp]
[225]196 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
[3]197 }
198
199 //fstp dword ptr[esp]
[225]200 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
[3]201 }
202 else SetError(9,NULL,cp);
203}
204
205void ChangeTypeToInt64(int OldType){
206 //現在のスタックの内容をInt64型に変換する
207 //NumOpeの直後専用
208 if(Is64Type(OldType)) return;
209
210 else if(OldType==DEF_DOUBLE){
211 //fld qword ptr[esp]
[225]212 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
[3]213
214 //fistp qword ptr[esp]
[225]215 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) );
[3]216 }
217 else if(OldType==DEF_SINGLE){
218 //fld dword ptr[esp]
[225]219 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
[3]220
221 //sub esp,4
[225]222 compiler.codeGenerator.op_sub_esp(4);
[3]223
224 //fistp qword ptr[esp]
[225]225 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) );
[3]226 }
227 else if(IsWholeNumberType(OldType)){
228 //その他整数
229
230 if(IsSignedType(OldType)){
231 //符号あり
232
233 //pop eax
[225]234 compiler.codeGenerator.op_pop(REG_EAX);
[3]235
236 //cdq
[225]237 compiler.codeGenerator.op_cdq();
[3]238
239 //push edx
[225]240 compiler.codeGenerator.op_push(REG_EDX);
[3]241
242 //push eax
[225]243 compiler.codeGenerator.op_push(REG_EAX);
[3]244 }
245 else{
246 //符号なし
247
248 //pop eax
[225]249 compiler.codeGenerator.op_pop(REG_EAX);
[3]250
251 //push 0
[225]252 compiler.codeGenerator.op_push_V(0);
[3]253
254 //push eax
[225]255 compiler.codeGenerator.op_push(REG_EAX);
[3]256 }
257 }
258 else SetError(9,NULL,cp);
259}
260void ChangeTypeToLong(int OldType){
261 //現在のスタックの内容をLong型に変換する
262 //NumOpeの直後専用
263 if(OldType==DEF_DOUBLE){
264
265 //fld qword ptr[esp]
[225]266 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
[3]267
268 //add esp,4
[225]269 compiler.codeGenerator.op_add_esp(4);
[3]270
271 //fistp dword ptr[esp]
[225]272 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) );
[3]273 }
274 else if(OldType==DEF_SINGLE){
275 //fld dword ptr[esp]
[225]276 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
[3]277
278 //fistp dword ptr[esp]
[225]279 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) );
[3]280 }
281 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
282 //pop eax
[225]283 compiler.codeGenerator.op_pop(REG_EAX);
[3]284
285 //add esp,4
[225]286 compiler.codeGenerator.op_add_esp(4);
[3]287
288 //push eax
[225]289 compiler.codeGenerator.op_push(REG_EAX);
[3]290 }
291}
292void ChangeTypeToInteger(int OldType){
293 //現在のスタックの内容をInteger型に変換する
[36]294 if(OldType==DEF_BOOLEAN||
295 OldType==DEF_BYTE||
[183]296 OldType==DEF_WORD||OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)) return;
297 else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){
[3]298 //pop eax
[225]299 compiler.codeGenerator.op_pop(REG_EAX);
[3]300
301 //movsx eax,al
[225]302 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
[3]303
304 //push eax
[225]305 compiler.codeGenerator.op_push(REG_EAX);
[3]306 }
307 else{
308 ChangeTypeToLong(OldType);
309
310 //pop eax
[225]311 compiler.codeGenerator.op_pop(REG_EAX);
[3]312
313 //and eax,0000FFFFh
[225]314 compiler.codeGenerator.op_and_RV( REG_EAX, 0x0000FFFF );
[3]315
316 //push eax
[225]317 compiler.codeGenerator.op_push(REG_EAX);
[3]318 }
319}
320void ChangeTypeToByte(int OldType){
321 //現在のスタックの内容をbyte型に変換する
[183]322 if(OldType==DEF_BYTE||OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)) return;
[3]323
324 ChangeTypeToLong(OldType);
325
326 //pop eax
[225]327 compiler.codeGenerator.op_pop(REG_EAX);
[3]328
329 //and eax,000000FFh
[225]330 compiler.codeGenerator.op_and_RV( REG_EAX, 0x000000FF );
[3]331
332 //push eax
[225]333 compiler.codeGenerator.op_push(REG_EAX);
[3]334}
335
[64]336
337
338
339
340
341
342
343
344void RestoreDefaultRegisterFromStackMemory( int type ){
345 //現在のスタックの内容を実数レジスタに保存する
346 //NumOpeの直後専用
347 if(type==DEF_DOUBLE){
348 //fld qword ptr[esp]
[225]349 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
[64]350
351 //add esp,8
[225]352 compiler.codeGenerator.op_add_esp(8);
[64]353 }
354 else if(type==DEF_SINGLE){
355 //fld dword ptr[esp]
[225]356 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
[64]357
358 //add esp,4
[225]359 compiler.codeGenerator.op_add_esp(4);
[64]360 }
361 else if( Is64Type( type ) ){
362 //pop eax
[225]363 compiler.codeGenerator.op_pop(REG_EAX);
[64]364
365 //pop edx
[225]366 compiler.codeGenerator.op_pop(REG_EDX);
[64]367 }
368 else{
369 //pop eax
[225]370 compiler.codeGenerator.op_pop(REG_EAX);
[64]371 }
372}
373
[290]374void SetVariableFromEax( const Type &varType,int CalcType,RELATIVE_VAR *pRelativeVar){
[64]375 /////////////////////////////////////////////////
376 // eaxの内容を変数にコピーするコードを抽出
377 /////////////////////////////////////////////////
378
[290]379 if( varType.IsBoolean() )
380 {
[64]381 //bool
382 SetBooleanVariable(CalcType,pRelativeVar);
383 }
[290]384 else if( varType.IsReal() )
385 {
[64]386 // Double/Single型変数へレジスタの値を代入
[290]387 SetRealVariable(varType.GetBasicType(), CalcType, pRelativeVar);
[64]388 }
[290]389 else if( varType.IsWhole() || varType.IsObject() )
390 {
391 int typeSize = varType.GetSize();
[64]392
393 //整数変数へraxの値を格納する
394 SetWholeVariable( typeSize, CalcType, pRelativeVar );
395 }
396 else{
397 SetError(300,NULL,cp);
398 }
399}
400
[129]401void OpcodeCalc( const char *Command ){
[3]402 int i,i2,i3;
403 char variable[VN_SIZE];
404
[75]405
406
407 //////////////////////////////////////
408 // インクリメント・デクリメント
409 //////////////////////////////////////
410
[3]411 for(i=0;;i++){
412 if(Command[i]=='\"'){
413 //ダブルクォートは不正なのでエラー扱い
414 variable[i]=0;
415 SetError(3,variable,cp);
416 return;
417 }
418
419 if(Command[i]=='('){
420 i2=GetStringInPare(variable+i,Command+i);
421 i+=i2-1;
422 continue;
423 }
424 if(Command[i]=='['){
425 i2=GetStringInBracket(variable+i,Command+i);
426 i+=i2-1;
427 continue;
428 }
429 if(Command[i]=='\0'){
430
431 ///////////////////////////////////
432 // インクリメント・デクリメント
433 ///////////////////////////////////
434
435 if(i>2){
436 if(Command[i-2]=='+'&&Command[i-1]=='+'){
437 //インクリメント
438 variable[i-2]=0;
439 IncDec(CALC_ADDITION,variable,"1");
440 return;
441 }
442 else if(Command[i-2]=='-'&&Command[i-1]=='-'){
443 //デクリメント
444 variable[i-2]=0;
445 IncDec(CALC_SUBTRACTION,variable,"1");
446 return;
447 }
448 }
449
450
451 //先端部分の識別子をエラーキーワードにする
452 for(i=0;;i++){
453 if(!IsVariableChar(Command[i])){
454 variable[i]=0;
455 break;
456 }
457 variable[i]=Command[i];
458 }
459
[75]460 if(GetVarType(variable,Type(),0)){
[3]461 //変数リストに該当したとき
462 SetError(1,NULL,cp);
463 }
464 else{
[265]465 if( compiler.GetObjectModule().meta.GetGlobalConsts().IsExist(variable)
466 || compiler.GetObjectModule().meta.GetGlobalConstMacros().IsExist(variable) )
[206]467 {
[3]468 //定数リストに該当したとき
469 SetError(1,NULL,cp);
470 }
471 else{
472 //変数リスト、定数リストに該当しないとき
473 SetError(3,variable,cp);
474 }
475 }
476 return;
477 }
478
479 i2=GetCalcId(Command+i,&i3);
480 if(i2){
481 variable[i]=0;
482
483 if(Command[i]=='=') break;
484
485 if(Command[i+1+i3]=='='){
486 IncDec(i2,variable,Command+i+1+i3+1);
487 return;
488 }
489 }
490
491 variable[i]=Command[i];
492 }
493
494 if(Command[i+1]=='\0'){
495 SetError(1,NULL,cp);
496 return;
497 }
498
499
500 ///////////////////////////////////////////////////////////////
501 // インデクサのsetアクセサ([]=演算子のオーバーロードに対応)
502 ///////////////////////////////////////////////////////////////
503
504 char ObjName[VN_SIZE],array_element[VN_SIZE];
505 GetArrayElement(variable,ObjName,array_element);
506 if(array_element[0]){
[75]507 Type varType;
508 if( GetVarType(ObjName,varType,0) && varType.IsObject() ){
[3]509 char temporary[VN_SIZE];
510 sprintf(temporary,"%s.%c%c%c",ObjName,1,ESC_OPERATOR,CALC_ARRAY_SET);
511
512 char temp2[VN_SIZE];
513 sprintf(temp2,"%s,%s",array_element,Command+i+1);
514
515 int idProc;
[75]516 void *pProc;
517 idProc=GetProc(temporary,(void **)&pProc);
[331]518 if( idProc )
519 {
520 CallProc(
521 idProc,
522 pProc,
523 temporary,
524 temp2,
525 Type(), // ベースタイプはなし
526 Type()
527 );
[3]528 return;
529 }
530 }
531 }
532
[64]533
534 if( lstrcmpi( variable, "This" ) == 0 ){
535 SetError(133,NULL,cp);
536 return;
537 }
538
539
[3]540 ////////////////////////////////////////
541 // 変数のタイプ型を識別して、演算を行う
542 ////////////////////////////////////////
543
[75]544 Type varType;
[3]545
546 //型を識別
[415]547 if( !GetTermTypeOnlyVariable(variable,varType) ){
[3]548
549 // プロパティ用のメソッドを呼び出す
[75]550 if(!CallPropertyMethod( variable, Command+i+1, Type() )){
[3]551 //エラーを表示
[75]552 GetVarType(variable,varType,true);
[3]553 }
554
555 return;
556 }
557
[75]558 RELATIVE_VAR VarRelativeVar;
559 if( varType.IsStruct() ){
[64]560 //代入コピーに備える
[3]561
562 //変数アドレスを取得
[11]563 if(!GetVarOffsetReadWrite(
[3]564 variable,
565 &VarRelativeVar,
[75]566 varType)) return;
[3]567
568 SetVarPtrToEax(&VarRelativeVar);
569
570 //push eax
[225]571 compiler.codeGenerator.op_push(REG_EAX);
[3]572 }
573
574 //NumOpe...(スタックに答えが格納される)
[75]575 BOOL bCalcUseHeap;
576 Type calcType;
577 if( !NumOpe(Command+i+1,varType,calcType,&bCalcUseHeap) ){
578 return;
579 }
[3]580
[179]581 if( calcType.IsObject() && !calcType.Equals( varType ) ){
582 bool isUpCast = false;
583 if( varType.IsObject() ){
584 if( varType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){
585 isUpCast = true;
586 }
587 }
588 if( !isUpCast ){
589 //キャスト演算子のオーバーロードに対応する
590 CallCastOperatorProc(calcType,bCalcUseHeap,varType);
591 }
592 }
593
[3]594 //変数アドレスを取得
[415]595 if( !TermOpeOnlyVariable( variable, varType, VarRelativeVar, true ) )
596 {
597 SetError();
598 return;
599 }
[3]600
[75]601 if(varType.GetBasicType()&FLAG_PTR){
[3]602 SetError(14,variable,cp);
603 return;
604 }
605
[75]606 if( varType.IsStruct() ){
607 //構造体インスタンスへの代入
608 SetStructVariable(varType,calcType,bCalcUseHeap);
[3]609 return;
610 }
611
612
[265]613 if( varType.IsObject() && compiler.GetObjectModule().meta.GetBlittableTypes().IsExist( calcType ) ){
[128]614 // Blittable型をオブジェクトとして扱う
[206]615 vector<const UserProc *> userProcs;
[265]616 compiler.GetObjectModule().meta.GetBlittableTypes().GetClass( calcType ).GetStaticMethods().Enum( "_Create", userProcs );
[128]617 if( userProcs.size() != 1 ){
618 SetError();
619 return;
620 }
[206]621 const UserProc *pUserProc = userProcs[0];
[3]622
[128]623 // call System.[TypeClass]._Create
[225]624 compiler.codeGenerator.op_call( pUserProc );
[128]625
626 // push eax
[225]627 compiler.codeGenerator.op_push( REG_EAX );
[128]628
629 calcType = pUserProc->ReturnType();
630 }
631
632
[3]633 /////////////////////////////////
634 // 右辺、左辺の型チェックを行う
635 /////////////////////////////////
636
[75]637 CheckDifferentType(varType,calcType,0,0);
[3]638
639
640 /////////////////////////////////////////////////
641 // スタックの内容を変数にコピーするコードを抽出
642 /////////////////////////////////////////////////
643
[64]644 //eax、edx:eax、またはst(0)にスタック上のデータを取り出す
[75]645 RestoreDefaultRegisterFromStackMemory( calcType.GetBasicType() );
[64]646
[290]647 SetVariableFromEax(varType,calcType.GetBasicType(),&VarRelativeVar);
[3]648}
Note: See TracBrowser for help on using the repository browser.