source: dev/trunk/abdev/BasicCompiler64/Compile_Calc.cpp @ 436

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

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

File size: 6.4 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <Compiler.h>
5
6#include "../BasicCompiler_Common/common.h"
7#include "Opcode.h"
8
9void SetVariableFromRax( const Type &varType, int CalcType,RELATIVE_VAR *pRelativeVar){
10    /////////////////////////////////////////////////
11    // raxの内容を変数にコピーするコードを抽出
12    /////////////////////////////////////////////////
13
14    if( varType.IsBoolean() )
15    {
16        //bool
17        SetBooleanVariable(CalcType,pRelativeVar);
18    }
19    else if( varType.IsReal() )
20    {
21        // Double/Single型変数へレジスタの値を代入
22        SetRealVariable(varType.GetBasicType(), CalcType, pRelativeVar);
23    }
24    else if( varType.IsWhole() || varType.IsObject() )
25    {
26        //整数変数へraxの値を格納する
27        SetWholeVariable( varType.GetSize(), CalcType, pRelativeVar );
28    }
29    else{
30        SetError(300,NULL,cp);
31    }
32}
33void OpcodeCalc(const char *Command){
34    int i,i2,i3;
35    char variable[VN_SIZE];
36
37
38    //////////////////////////////////////
39    // インクリメント・デクリメント
40    //////////////////////////////////////
41
42    for(i=0;;i++){
43        if(Command[i]=='\"'){
44            //ダブルクォートは不正なのでエラー扱い
45            variable[i]=0;
46            SetError(3,variable,cp);
47            return;
48        }
49
50        if(Command[i]=='('){
51            i2=GetStringInPare(variable+i,Command+i);
52            i+=i2-1;
53            continue;
54        }
55        if(Command[i]=='['){
56            i2=GetStringInBracket(variable+i,Command+i);
57            i+=i2-1;
58            continue;
59        }
60        if(Command[i]=='\0'){
61
62            ///////////////////////////////////
63            // インクリメント・デクリメント
64            ///////////////////////////////////
65
66            if(i>2){
67                if(Command[i-2]=='+'&&Command[i-1]=='+'){
68                    //インクリメント
69                    variable[i-2]=0;
70                    IncDec(CALC_ADDITION,variable,"1");
71                    return;
72                }
73                else if(Command[i-2]=='-'&&Command[i-1]=='-'){
74                    //デクリメント
75                    variable[i-2]=0;
76                    IncDec(CALC_SUBTRACTION,variable,"1");
77                    return;
78                }
79            }
80
81
82            //先端部分の識別子をエラーキーワードにする
83            for(i=0;;i++){
84                if(!IsVariableChar(Command[i])){
85                    variable[i]=0;
86                    break;
87                }
88                variable[i]=Command[i];
89            }
90
91            if(GetVarType(variable,Type(),0)){
92                //変数リストに該当したとき
93                SetError(1,NULL,cp);
94            }
95            else{
96                if( compiler.GetObjectModule().meta.GetGlobalConsts().IsExist(variable)
97                    || compiler.GetObjectModule().meta.GetGlobalConstMacros().IsExist(variable) )
98                {
99                    //定数リストに該当したとき
100                    SetError(1,NULL,cp);
101                }
102                else{
103                    //変数リスト、定数リストに該当しないとき
104                    SetError(3,variable,cp);
105                }
106            }
107            return;
108        }
109
110        i2=GetCalcId(Command+i,&i3);
111        if(i2){
112            variable[i]=0;
113
114            if(Command[i]=='=') break;
115
116            if(Command[i+1+i3]=='='){
117                IncDec(i2,variable,Command+i+1+i3+1);
118                return;
119            }
120        }
121
122        variable[i]=Command[i];
123    }
124
125    if(Command[i+1]=='\0'){
126        SetError(1,NULL,cp);
127        return;
128    }
129
130
131
132    ///////////////////////////////////////////////////////////////
133    // インデクサのsetアクセサ([]=演算子のオーバーロードに対応)
134    ///////////////////////////////////////////////////////////////
135
136    char ObjName[VN_SIZE],array_element[VN_SIZE];
137    GetArrayElement(variable,ObjName,array_element);
138    if(array_element[0]){
139        Type varType;
140        if( GetVarType(ObjName,varType,0) && varType.IsObject() ){
141            char temporary[VN_SIZE];
142            sprintf(temporary,"%s.%c%c%c",ObjName,1,ESC_OPERATOR,CALC_ARRAY_SET);
143
144            char temp2[VN_SIZE];
145            sprintf(temp2,"%s,%s",array_element,Command+i+1);
146
147            int idProc;
148            void *pProc;
149            idProc=GetProc(temporary,(void **)&pProc);
150            if( idProc )
151            {
152                CallProc(
153                    idProc,
154                    pProc,
155                    temporary,
156                    temp2,
157                    Type(),         // ベースタイプはなし
158                    Type()
159                );
160                return;
161            }
162        }
163    }
164
165
166    if( lstrcmpi( variable, "This" ) == 0 ){
167        SetError(133,NULL,cp);
168        return;
169    }
170
171
172    ////////////////////////////////////////
173    // 変数のタイプ型を識別して、演算を行う
174    ////////////////////////////////////////
175
176    Type varType;
177
178    //型を識別
179    if( !GetTermTypeOnlyVariable(variable,varType) ){
180
181        // プロパティ用のメソッドを呼び出す
182        if(!CallPropertyMethod( variable, Command+i+1, Type() )){
183            //エラーを表示
184            GetVarType(variable,varType,true);
185        }
186
187        return;
188    }
189
190    //NumOpe...(rax、またはxmm0に答えが格納される)
191    int reg=REG_RAX;
192    Type calcType;
193    bool isNeedHeapFreeStructure;
194    if( !NumOpe(&reg,Command+i+1,varType,calcType,&isNeedHeapFreeStructure) ){
195        return;
196    }
197
198    if(reg!=REG_RAX&&calcType.IsWhole()||
199        varType.IsNull()||calcType.IsNull()){
200        SetError(300,NULL,cp);
201    }
202
203    //結果を格納しているレジスタをブロッキング
204    pobj_BlockReg->lock(reg);
205
206    //変数アドレスを取得
207    RELATIVE_VAR VarRelativeVar;
208    if( !TermOpeOnlyVariable( variable, varType, VarRelativeVar, true ) )
209    {
210        SetError();
211        return;
212    }
213
214    //レジスタのブロッキングを解除
215    pobj_BlockReg->clear();
216
217    if(varType.GetBasicType()&FLAG_PTR){
218        SetError(14,variable,cp);
219        return;
220    }
221
222    if( varType.IsStruct() ){
223        //構造体インスタンスへの代入
224        SetStructVariableFromRax(varType,calcType,&VarRelativeVar,isNeedHeapFreeStructure);
225        return;
226    }
227
228    if( calcType.IsObject() && !calcType.Equals( varType ) ){
229        bool isUpCast = false;
230        if( varType.IsObject() ){
231            if( varType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){
232                isUpCast = true;
233            }
234        }
235        if( !isUpCast ){
236            //キャスト演算子のオーバーロードに対応する
237            CallCastOperatorProc(REG_RAX,calcType,isNeedHeapFreeStructure,varType);
238        }
239    }
240
241    if( varType.IsObject() && compiler.GetObjectModule().meta.GetBlittableTypes().IsExist( calcType ) ){
242        // Blittable型をオブジェクトとして扱う
243        vector<const UserProc *> userProcs;
244        compiler.GetObjectModule().meta.GetBlittableTypes().GetClass( calcType ).GetStaticMethods().Enum( "_Create", userProcs );
245        if( userProcs.size() != 1 ){
246            SetError();
247            return;
248        }
249        const UserProc *pUserProc = userProcs[0];
250
251        // mov rcx, rax
252        compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RAX );
253
254        // call System.[TypeClass]._Create
255        compiler.codeGenerator.op_call( pUserProc );
256
257        calcType = pUserProc->ReturnType();
258    }
259
260    /////////////////////////////////
261    // 右辺、左辺の型チェックを行う
262    /////////////////////////////////
263
264    CheckDifferentType(varType,calcType,0,0);
265
266
267    /////////////////////////////////////////////////
268    // rax(実数はxmm0)の内容を変数にコピー
269    /////////////////////////////////////////////////
270    SetVariableFromRax(varType,calcType.GetBasicType(),&VarRelativeVar);
271
272
273    // コード生成過程で発生した構造体の一時メモリを破棄する
274    compiler.codeGenerator.op_FreeTempStructure();
275}
Note: See TracBrowser for help on using the repository browser.