source: dev/trunk/abdev/BasicCompiler32/OperatorProc.cpp@ 424

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

・ジェネリックな型をパラメータに持つメソッドのオーバーロード解決に対応した。
・型パラメータの制約クラス指定に対応した。

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