source: dev/trunk/ab5.0/abdev/BasicCompiler32/OperatorProc.cpp @ 465

Last change on this file since 465 was 465, checked in by dai_9181, 15 years ago

Messenger/ErrorMessengerクラスを導入。SetError関数によるエラー生成を廃止した。

File size: 6.4 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4
5#include "../BasicCompiler_Common/common.h"
6#include "Opcode.h"
7
8void FreeTempObject(int reg,const CClass *pobj_c){
9    if(!IsSafeReg(reg)) compiler.errorMessenger.Output(300,NULL,cp);
10
11    const CMethod *method = pobj_c->GetDestructorMethod();
12    if( method ){
13        //push reg
14        compiler.codeGenerator.op_push(reg);
15
16        //call DestructorProcAddr
17        compiler.codeGenerator.op_call( &method->GetUserProc() );
18    }
19
20    //push reg
21    compiler.codeGenerator.op_push(reg);
22
23    //call free
24    extern const UserProc *pSub_free;
25    compiler.codeGenerator.op_call(pSub_free);
26}
27
28int CallOperatorProc(int idCalc, const Type &baseType, int *type_stack, LONG_PTR *index_stack,bool isNeedHeapFreeStructureStack[],int &sp)
29{
30    Type leftType( type_stack[sp-2], index_stack[sp-2] );
31    Type rightType( type_stack[sp-1] & (~FLAG_CAST), index_stack[sp-1] );
32
33    //オーバーロードされたオペレータ関数を呼び出す
34    const CClass *pobj_c = &leftType.GetClass();
35
36    std::vector<const UserProc *> subs;
37    pobj_c->GetDynamicMethods().Enum( idCalc, subs );
38    if( subs.size() == 0 ){
39        return 0;
40    }
41
42
43    //項の数
44    BOOL bTwoTerm=1;
45    if(idCalc==CALC_AS) bTwoTerm=0;
46
47
48    /////////////////////////////////////////////
49    // オーバーロード解決用のパラメータを設定
50    /////////////////////////////////////////////
51
52    Parameters params;
53
54    if(bTwoTerm){
55        params.push_back( new Parameter( "", rightType ) );
56    }
57
58    //オーバーロードを解決
59    char temporary[255];
60    if(idCalc==CALC_EQUAL) lstrcpy(temporary,"==");
61    else GetCalcName(idCalc,temporary);
62    const UserProc *pUserProc = OverloadSolution( temporary, subs, params, baseType, leftType );
63
64    if(!pUserProc){
65        if(bTwoTerm){
66            delete params[0];
67        }
68        return -1;
69    }
70    else{
71        //オーバーロードされていないが、パラメータ個数が一致しないとき
72        if(params.size()!=pUserProc->Params().size()){
73            if(bTwoTerm){
74                delete params[0];
75            }
76            return -1;
77        }
78    }
79
80    for(int i=0;i<(int)params.size();i++){
81        CheckDifferentType(
82            *pUserProc->Params()[i],
83            *params[i],
84            NULL,
85            i);
86    }
87
88    if(bTwoTerm){
89        delete params[0];
90    }
91
92    int right_side_size = rightType.GetSize();
93
94    if(bTwoTerm){
95        if( pUserProc->RealParams()[1]->IsStruct() &&pUserProc->RealParams()[1]->IsRef() == false ){
96            //一時オブジェクトはメソッド内で破棄される
97            isNeedHeapFreeStructureStack[sp-1] = false;
98        }
99    }
100
101
102    if( pUserProc->ReturnType().IsStruct() ){
103        //////////////////////////////////////////////////////
104        // 戻り値に構造体インスタンスを持つ場合
105        // ※ByRef _System_ReturnValue パラメータ用領域を取得
106        //////////////////////////////////////////////////////
107
108        int object_size = pUserProc->ReturnType().GetClass().GetSize();
109
110        //push object_size
111        compiler.codeGenerator.op_push_V(object_size);
112
113        //call calloc
114        extern const UserProc *pSub_calloc;
115        compiler.codeGenerator.op_call(pSub_calloc);
116
117        //mov ebx,eax
118        compiler.codeGenerator.op_mov_RR(REG_EBX,REG_EAX);
119    }
120
121
122    //2つの項を取り出す
123    if(bTwoTerm){
124        if(right_side_size==sizeof(_int64)){
125            //pop eax
126            compiler.codeGenerator.op_pop(REG_EAX);
127
128            //pop edx
129            compiler.codeGenerator.op_pop(REG_EDX);
130        }
131        else{
132            //pop eax
133            compiler.codeGenerator.op_pop(REG_EAX);
134        }
135    }
136
137    //pop ecx
138    compiler.codeGenerator.op_pop(REG_ECX);
139
140
141    //ヒープ解放用に退避
142    if(isNeedHeapFreeStructureStack[sp-1]){
143        //mov esi,eax
144        compiler.codeGenerator.op_mov_RR(REG_ESI,REG_EAX);
145    }
146    if(isNeedHeapFreeStructureStack[sp-2]){
147        //mov edi,ecx
148        compiler.codeGenerator.op_mov_RR(REG_EDI,REG_ECX);
149    }
150
151
152
153    if(bTwoTerm){
154        if(right_side_size==sizeof(_int64)){
155            //push edx
156            compiler.codeGenerator.op_push(REG_EDX);
157
158            //push eax
159            compiler.codeGenerator.op_push(REG_EAX);
160        }
161        else{
162            //push eax
163            compiler.codeGenerator.op_push(REG_EAX);
164        }
165
166        if( pUserProc->RealParams()[1]->IsRef() ){
167            //一時参照を作成
168
169            //mov eax,esp
170            compiler.codeGenerator.op_mov_RR( REG_EAX, REG_ESP );
171
172            //push eax
173            compiler.codeGenerator.op_push( REG_EAX );
174        }
175    }
176
177    if( pUserProc->ReturnType().IsStruct() ){
178        //push ebx
179        compiler.codeGenerator.op_push(REG_EBX);
180    }
181
182    //push ecx
183    compiler.codeGenerator.op_push(REG_ECX);
184
185    //call operator_proc
186    compiler.codeGenerator.op_call(pUserProc);
187
188    if(bTwoTerm){
189        if( pUserProc->RealParams()[1]->IsRef() ){
190            //一時参照を破棄
191            compiler.codeGenerator.op_pop( REG_NON );
192        }
193    }
194
195    if( !pUserProc->ReturnType().IsNull() ){
196        //スタックへプッシュ
197        PushReturnValue(pUserProc->ReturnType().GetBasicType());
198    }
199
200    if(isNeedHeapFreeStructureStack[sp-1]){
201        FreeTempObject(REG_ESI,(CClass *)index_stack[sp-1]);
202    }
203    if(isNeedHeapFreeStructureStack[sp-2]){
204        FreeTempObject(REG_EDI,(CClass *)index_stack[sp-2]);
205    }
206
207    sp--;
208    type_stack[sp-1]=pUserProc->ReturnType().GetBasicType();
209    index_stack[sp-1]=pUserProc->ReturnType().GetIndex();
210
211    if( pUserProc->ReturnType().IsStruct() )
212    {
213        //構造体が戻ったときはヒープ領域にインスタンスが格納されている
214        //※後にfreeする必要あり
215        isNeedHeapFreeStructureStack[sp-1] = true;
216    }
217    else
218    {
219        isNeedHeapFreeStructureStack[sp-1] = false;
220    }
221
222    return 1;
223}
224
225void CallCastOperatorProc(Type &calcType,BOOL bCalcUseHeap,const Type &toType){
226    int type_stack[10];
227    LONG_PTR index_stack[10];
228    bool array_bUseHeap[10];
229    int sp=2;
230
231    if(bCalcUseHeap){
232        //未解放のインスタンスが存在する旨を示す警告
233        compiler.errorMessenger.Output(-105,NULL,cp);
234    }
235
236    //左辺
237    type_stack[0]=calcType.GetBasicType();
238    index_stack[0]=calcType.GetIndex();
239    array_bUseHeap[0]=0;
240    type_stack[1]=toType.GetBasicType();
241    index_stack[1]=toType.GetIndex();
242    array_bUseHeap[1]=0;
243
244    int iRet = CallOperatorProc(CALC_AS,toType,type_stack,index_stack,array_bUseHeap,sp);
245
246    if(iRet==1){
247        //成功したとき
248        calcType.SetType( type_stack[0], index_stack[0] );
249        return;
250    }
251    else if(iRet==-1){
252        //エラーが発行されたとき
253        return;
254    }
255
256    //エラーを発行
257    compiler.errorMessenger.Output(-1,"キャスト演算子がオーバーロードされていません。",cp);
258}
259void CallIndexerGetterProc( const Type &classType, const char *ObjectName, char *Parameter,Type &resultType, DWORD dwProcFlags ){
260    std::vector<const UserProc *> subs;
261    classType.GetClass().GetDynamicMethods().Enum( CALC_ARRAY_GET, subs );
262    if( subs.size() == 0 ){
263        return;
264    }
265
266    const UserProc *pUserProc = subs[0];
267
268    Opcode_CallProc(Parameter,pUserProc,dwProcFlags,ObjectName);
269    resultType = pUserProc->ReturnType();
270
271    // 型パラメータを解決
272    ResolveFormalGenericTypeParameter( resultType, classType, pUserProc );
273}
Note: See TracBrowser for help on using the repository browser.