source: dev/trunk/ab5.0/abdev/BasicCompiler32/Compile_Calc.cpp@ 445

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

関数の戻り値の構造体など、一時メモリに保持された構造体のメンバに直接アクセスした場合、その一時メモリの解放が正常に行われないバグを修正(64bit版も修正した)。

File size: 14.8 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
10void ChangeTypeToDouble_ToFpuReg(int OldType){
11 //現在のスタックの内容を実数レジスタに保存する
12 //NumOpeの直後専用
13 if(OldType==DEF_DOUBLE){
14 //fld qword ptr[esp]
15 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
16
17 //add esp,8
18 compiler.codeGenerator.op_add_esp(8);
19 }
20 else if(OldType==DEF_SINGLE){
21 //fld dword ptr[esp]
22 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
23
24 //add esp,4
25 compiler.codeGenerator.op_add_esp(4);
26 }
27 else if(OldType==DEF_LONG){
28 //fild dword ptr[esp]
29 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
30
31 //add esp,4
32 compiler.codeGenerator.op_add_esp(4);
33 }
34 else if(OldType==DEF_DWORD){
35 //pop eax
36 compiler.codeGenerator.op_pop(REG_EAX);
37
38 //push 0
39 compiler.codeGenerator.op_push_V(0);
40
41 //push eax
42 compiler.codeGenerator.op_push(REG_EAX);
43
44 //fild qword ptr[esp]
45 compiler.codeGenerator.PutOld(
46 (char)0xDF,
47 (char)0x2C,
48 (char)0x24
49 );
50
51 //add esp,8
52 compiler.codeGenerator.op_add_esp(8);
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]
61 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
62
63 //sub esp,4
64 compiler.codeGenerator.op_sub_esp(4);
65
66 //fstp qword ptr[esp]
67 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
68 }
69 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
70 //64ビット整数型
71
72 //fild qword ptr[esp]
73 compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64);
74
75 //fstp qword ptr[esp]
76 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
77 }
78 else if(IsWholeNumberType(OldType)){
79 //その他整数型
80
81 if(IsSignedType(OldType)){
82 //符号あり
83
84 if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){
85 //pop eax
86 compiler.codeGenerator.op_pop(REG_EAX);
87
88 //movsx eax,ax
89 compiler.codeGenerator.op_movsx_R32R16( REG_EAX );
90
91 //push eax
92 compiler.codeGenerator.op_push(REG_EAX);
93 }
94 else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){
95 //pop eax
96 compiler.codeGenerator.op_pop(REG_EAX);
97
98 //movsx eax,al
99 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
100
101 //push eax
102 compiler.codeGenerator.op_push(REG_EAX);
103 }
104
105 //fild dword ptr[esp]
106 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
107
108 //sub esp,4
109 compiler.codeGenerator.op_sub_esp(4);
110 }
111 else{
112 //符号なし
113
114 //pop eax
115 compiler.codeGenerator.op_pop(REG_EAX);
116
117 //push 0
118 compiler.codeGenerator.op_push_V(0);
119
120 //push eax
121 compiler.codeGenerator.op_push(REG_EAX);
122
123 //fild qword ptr[esp]
124 compiler.codeGenerator.PutOld(
125 (char)0xDF,
126 (char)0x2C,
127 (char)0x24
128 );
129 }
130
131 //fstp qword ptr[esp]
132 compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
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]
142 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
143
144 //add esp,4
145 compiler.codeGenerator.op_add_esp(4);
146
147 //fstp dword ptr[esp]
148 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
149 }
150 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
151 //64ビット整数型
152
153 //fild qword ptr[esp]
154 compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64);
155
156 //add esp,4
157 compiler.codeGenerator.op_add_esp(4);
158
159 //fstp dword ptr[esp]
160 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
161 }
162 else if(IsWholeNumberType(OldType)){
163 //その他整数型
164
165 if(IsSignedType(OldType)){
166 //符号あり
167
168 if(OldType==DEF_INTEGER || (Smoothie::IsUnicode()&&OldType==DEF_CHAR)){
169 //pop eax
170 compiler.codeGenerator.op_pop(REG_EAX);
171
172 //movsx eax,ax
173 compiler.codeGenerator.op_movsx_R32R16( REG_EAX );
174
175 //push eax
176 compiler.codeGenerator.op_push(REG_EAX);
177 }
178 else if(OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)){
179 //pop eax
180 compiler.codeGenerator.op_pop(REG_EAX);
181
182 //movsx eax,al
183 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
184
185 //push eax
186 compiler.codeGenerator.op_push(REG_EAX);
187 }
188
189 //fild dword ptr[esp]
190 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
191 }
192 else{
193 //符号なし
194
195 //fild dword ptr[esp]
196 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
197 }
198
199 //fstp dword ptr[esp]
200 compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
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]
212 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
213
214 //fistp qword ptr[esp]
215 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) );
216 }
217 else if(OldType==DEF_SINGLE){
218 //fld dword ptr[esp]
219 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
220
221 //sub esp,4
222 compiler.codeGenerator.op_sub_esp(4);
223
224 //fistp qword ptr[esp]
225 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) );
226 }
227 else if(IsWholeNumberType(OldType)){
228 //その他整数
229
230 if(IsSignedType(OldType)){
231 //符号あり
232
233 //pop eax
234 compiler.codeGenerator.op_pop(REG_EAX);
235
236 //cdq
237 compiler.codeGenerator.op_cdq();
238
239 //push edx
240 compiler.codeGenerator.op_push(REG_EDX);
241
242 //push eax
243 compiler.codeGenerator.op_push(REG_EAX);
244 }
245 else{
246 //符号なし
247
248 //pop eax
249 compiler.codeGenerator.op_pop(REG_EAX);
250
251 //push 0
252 compiler.codeGenerator.op_push_V(0);
253
254 //push eax
255 compiler.codeGenerator.op_push(REG_EAX);
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]
266 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
267
268 //add esp,4
269 compiler.codeGenerator.op_add_esp(4);
270
271 //fistp dword ptr[esp]
272 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) );
273 }
274 else if(OldType==DEF_SINGLE){
275 //fld dword ptr[esp]
276 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
277
278 //fistp dword ptr[esp]
279 compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) );
280 }
281 else if(OldType==DEF_INT64||OldType==DEF_QWORD){
282 //pop eax
283 compiler.codeGenerator.op_pop(REG_EAX);
284
285 //add esp,4
286 compiler.codeGenerator.op_add_esp(4);
287
288 //push eax
289 compiler.codeGenerator.op_push(REG_EAX);
290 }
291}
292void ChangeTypeToInteger(int OldType){
293 //現在のスタックの内容をInteger型に変換する
294 if(OldType==DEF_BOOLEAN||
295 OldType==DEF_BYTE||
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)){
298 //pop eax
299 compiler.codeGenerator.op_pop(REG_EAX);
300
301 //movsx eax,al
302 compiler.codeGenerator.op_movsx_R32R8( REG_EAX );
303
304 //push eax
305 compiler.codeGenerator.op_push(REG_EAX);
306 }
307 else{
308 ChangeTypeToLong(OldType);
309
310 //pop eax
311 compiler.codeGenerator.op_pop(REG_EAX);
312
313 //and eax,0000FFFFh
314 compiler.codeGenerator.op_and_RV( REG_EAX, 0x0000FFFF );
315
316 //push eax
317 compiler.codeGenerator.op_push(REG_EAX);
318 }
319}
320void ChangeTypeToByte(int OldType){
321 //現在のスタックの内容をbyte型に変換する
322 if(OldType==DEF_BYTE||OldType==DEF_SBYTE || (Smoothie::IsUnicode()==false&&OldType==DEF_CHAR)) return;
323
324 ChangeTypeToLong(OldType);
325
326 //pop eax
327 compiler.codeGenerator.op_pop(REG_EAX);
328
329 //and eax,000000FFh
330 compiler.codeGenerator.op_and_RV( REG_EAX, 0x000000FF );
331
332 //push eax
333 compiler.codeGenerator.op_push(REG_EAX);
334}
335
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]
349 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
350
351 //add esp,8
352 compiler.codeGenerator.op_add_esp(8);
353 }
354 else if(type==DEF_SINGLE){
355 //fld dword ptr[esp]
356 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
357
358 //add esp,4
359 compiler.codeGenerator.op_add_esp(4);
360 }
361 else if( Is64Type( type ) ){
362 //pop eax
363 compiler.codeGenerator.op_pop(REG_EAX);
364
365 //pop edx
366 compiler.codeGenerator.op_pop(REG_EDX);
367 }
368 else{
369 //pop eax
370 compiler.codeGenerator.op_pop(REG_EAX);
371 }
372}
373
374void SetVariableFromEax( const Type &varType,int CalcType,RELATIVE_VAR *pRelativeVar){
375 /////////////////////////////////////////////////
376 // eaxの内容を変数にコピーするコードを抽出
377 /////////////////////////////////////////////////
378
379 if( varType.IsBoolean() )
380 {
381 //bool
382 SetBooleanVariable(CalcType,pRelativeVar);
383 }
384 else if( varType.IsReal() )
385 {
386 // Double/Single型変数へレジスタの値を代入
387 SetRealVariable(varType.GetBasicType(), CalcType, pRelativeVar);
388 }
389 else if( varType.IsWhole() || varType.IsObject() )
390 {
391 int typeSize = varType.GetSize();
392
393 //整数変数へraxの値を格納する
394 SetWholeVariable( typeSize, CalcType, pRelativeVar );
395 }
396 else{
397 SetError(300,NULL,cp);
398 }
399}
400
401void OpcodeCalc( const char *Command ){
402 int i,i2,i3;
403 char variable[VN_SIZE];
404
405
406
407 //////////////////////////////////////
408 // インクリメント・デクリメント
409 //////////////////////////////////////
410
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
460 if(GetVarType(variable,Type(),0)){
461 //変数リストに該当したとき
462 SetError(1,NULL,cp);
463 }
464 else{
465 if( compiler.GetObjectModule().meta.GetGlobalConsts().IsExist(variable)
466 || compiler.GetObjectModule().meta.GetGlobalConstMacros().IsExist(variable) )
467 {
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]){
507 Type varType;
508 if( GetVarType(ObjName,varType,0) && varType.IsObject() ){
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;
516 void *pProc;
517 idProc=GetProc(temporary,(void **)&pProc);
518 if( idProc )
519 {
520 CallProc(
521 idProc,
522 pProc,
523 temporary,
524 temp2,
525 Type(), // ベースタイプはなし
526 Type()
527 );
528 return;
529 }
530 }
531 }
532
533
534 if( lstrcmpi( variable, "This" ) == 0 ){
535 SetError(133,NULL,cp);
536 return;
537 }
538
539
540 ////////////////////////////////////////
541 // 変数のタイプ型を識別して、演算を行う
542 ////////////////////////////////////////
543
544 Type varType;
545
546 //型を識別
547 if( !GetTermTypeOnlyVariable(variable,varType) ){
548
549 // プロパティ用のメソッドを呼び出す
550 if(!CallPropertyMethod( variable, Command+i+1, Type() )){
551 //エラーを表示
552 GetVarType(variable,varType,true);
553 }
554
555 return;
556 }
557
558 RELATIVE_VAR VarRelativeVar;
559 if( varType.IsStruct() ){
560 //代入コピーに備える
561
562 //変数アドレスを取得
563 if(!GetVarOffsetReadWrite(
564 variable,
565 &VarRelativeVar,
566 varType)) return;
567
568 SetVarPtrToEax(&VarRelativeVar);
569
570 //push eax
571 compiler.codeGenerator.op_push(REG_EAX);
572 }
573
574 //NumOpe...(スタックに答えが格納される)
575 Type calcType;
576 bool isNeedHeapFreeStructure;
577 if( !NumOpe(Command+i+1,varType,calcType,&isNeedHeapFreeStructure) ){
578 return;
579 }
580
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,isNeedHeapFreeStructure,varType);
591 }
592 }
593
594 //変数アドレスを取得
595 if( !TermOpeOnlyVariable( variable, varType, VarRelativeVar, true ) )
596 {
597 SetError();
598 return;
599 }
600
601 if(varType.GetBasicType()&FLAG_PTR){
602 SetError(14,variable,cp);
603 return;
604 }
605
606 if( varType.IsStruct() ){
607 //構造体インスタンスへの代入
608 SetStructVariable(varType,calcType,isNeedHeapFreeStructure);
609 return;
610 }
611
612
613 if( varType.IsObject() && compiler.GetObjectModule().meta.GetBlittableTypes().IsExist( calcType ) ){
614 // Blittable型をオブジェクトとして扱う
615 vector<const UserProc *> userProcs;
616 compiler.GetObjectModule().meta.GetBlittableTypes().GetClass( calcType ).GetStaticMethods().Enum( "_Create", userProcs );
617 if( userProcs.size() != 1 ){
618 SetError();
619 return;
620 }
621 const UserProc *pUserProc = userProcs[0];
622
623 // call System.[TypeClass]._Create
624 compiler.codeGenerator.op_call( pUserProc );
625
626 // push eax
627 compiler.codeGenerator.op_push( REG_EAX );
628
629 calcType = pUserProc->ReturnType();
630 }
631
632
633 /////////////////////////////////
634 // 右辺、左辺の型チェックを行う
635 /////////////////////////////////
636
637 CheckDifferentType(varType,calcType,0,0);
638
639
640 /////////////////////////////////////////////////
641 // スタックの内容を変数にコピーするコードを抽出
642 /////////////////////////////////////////////////
643
644 //eax、edx:eax、またはst(0)にスタック上のデータを取り出す
645 RestoreDefaultRegisterFromStackMemory( calcType.GetBasicType() );
646
647 SetVariableFromEax(varType,calcType.GetBasicType(),&VarRelativeVar);
648
649
650 // コード生成過程で発生した構造体の一時メモリを破棄する
651 compiler.codeGenerator.op_FreeTempStructure();
652}
Note: See TracBrowser for help on using the repository browser.