source: dev/trunk/abdev/BasicCompiler32/CParameter.cpp@ 435

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

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

File size: 9.4 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4
5#include "../BasicCompiler_Common/common.h"
6#include "opcode.h"
7
8int ParamImpl::NewTempParameters( const string &procName, const Parameters &params, int SecondParmNum ){
9 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
10
11 ///////////////////////////////////////////////////////
12 // 一時オブジェクトをあらかじめスタックに積んでおく
13 ///////////////////////////////////////////////////////
14
15 useTempObject = false;
16
17 //一時参照の数
18 nCountOfTempObjects = 0;
19
20 BOOL bEllipse;
21 if(params.size()){
22 if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1;
23 else bEllipse=0;
24 }
25 else bEllipse=0;
26
27 for(int i2=ParmsNum-1;i2>=0;i2--){
28 useTempParameters[i2] = false;
29
30 if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0;
31
32 if(i2==0){
33 if( params[i2]->GetVarName() == "_System_LocalThis" ){
34 //オブジェクトメンバの第一パラメータのThisポインタ
35 continue;
36 }
37 }
38 if( i2==0||i2==1 ){
39 if( params[i2]->GetVarName() == procName ){
40 //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト
41 continue;
42 }
43 }
44
45 Type dummyType;
46 BOOL bByVal;
47 if(bEllipse){
48 NumOpe_GetType( Parms[i2], Type(), dummyType );
49 bByVal=1;
50 }
51 else{
52 dummyType = *params[i2];
53 bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE;
54 }
55
56
57 if( !bByVal ){
58 //ポインタ参照
59 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
60 //ポインタ指定
61 continue;
62 }
63
64 if( !GetVarType( Parms[i2], Type(), FALSE ) ){
65 //変数ではないとき
66 Type calcType;
67 BOOL bUseHeap;
68 NumOpe( Parms[i2], dummyType, calcType, &bUseHeap );
69 //↑ここでスタックに積む
70
71 nCountOfTempObjects++;
72
73 if( !calcType.IsStruct() ){
74 //一時参照を作成
75
76 //push esp
77 compiler.codeGenerator.op_push( REG_ESP );
78
79 nCountOfTempObjects++;
80 }
81
82 bool result = CheckDifferentType(
83 dummyType,
84 calcType,
85 procName.c_str(),
86 i2);
87
88 if( result && bUseHeap ){
89 useTempParameters[i2] = true;
90 useTempObject = true;
91
92 types[i2] = calcType;
93 }
94 }
95 }
96 }
97
98 return nCountOfTempObjects * PTR_SIZE;
99}
100
101void ParamImpl::DeleteTempParameters(){
102 ///////////////////////////////////////////////////////
103 // 一時オブジェクトを破棄
104 ///////////////////////////////////////////////////////
105 if( !useTempObject ) return;
106
107 for(int i2=ParmsNum-1;i2>=0;i2--){
108 if( useTempParameters[i2] ){
109 if( types[i2].IsStruct() ){
110 // 構造体の一時メモリ
111
112 //メモリを解放する
113
114 //call free
115 extern const UserProc *pSub_free;
116 compiler.codeGenerator.op_call(pSub_free);
117 }
118 else{
119 if( types[i2].Is64() ){
120 //pop ... 参照を消す
121 //pop ... 上位32ビット
122 //pop ... 下位32ビット
123 compiler.codeGenerator.op_add_esp( PTR_SIZE * 3 );
124 }
125 else{
126 //pop ... 参照を消す
127 //pop ... 値を消す
128 compiler.codeGenerator.op_add_esp( PTR_SIZE * 2 );
129 }
130 }
131 }
132 }
133}
134
135void ParamImpl::SetStructParameter( const Type &baseType, const char *expression ){
136 int object_size = baseType.GetClass().GetSize();
137
138 //push object_size
139 compiler.codeGenerator.op_push_V(object_size);
140
141 //call calloc
142 extern const UserProc *pSub_calloc;
143 compiler.codeGenerator.op_call(pSub_calloc);
144
145 //push eax(ここでプッシュされた値が実際にパラメータとして引き渡される)
146 compiler.codeGenerator.op_push(REG_EAX);
147
148 //push eax
149 compiler.codeGenerator.op_push(REG_EAX);
150
151 Type calcType;
152 BOOL bUseHeap;
153 NumOpe( expression,
154 baseType,
155 calcType,
156 &bUseHeap );
157
158 // ※スタックにある二つのデータ(コピー先、コピー元)の値を必要とする
159 SetStructVariable( baseType, calcType, bUseHeap );
160}
161
162int ParamImpl::SetParameter( const string &procName, const Parameters &params, int SecondParmNum, const UserProc *pUserProc ){
163 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
164
165 ///////////////////////////////////////////////////////////
166 // パラメータをレジスタ及びスタックフレームにセット
167 ///////////////////////////////////////////////////////////
168 int i2,i3;
169
170 BOOL bEllipse;
171 if( params.size() ){
172 if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1;
173 else bEllipse=0;
174 }
175 else bEllipse=0;
176
177 BOOL bHas_System_LocalThis=0;
178 if(ParmsNum>=1){
179 if( params[0]->GetVarName() == "_System_LocalThis" ){
180 bHas_System_LocalThis=1;
181 }
182 }
183
184 //戻り値用の変数名を取得
185 const char *lpszVarNameToReturn = (procName[0]==1&&procName[1]==ESC_OPERATOR)?"_System_ReturnValue":procName.c_str();
186
187 //パラメータをレジスタとスタックに格納
188 int ParmSize=0;
189 RELATIVE_VAR RelativeVar;
190 int nCountOfNowTempObjects = 0;
191 for(i2=ParmsNum-1;i2>=0;i2--){
192 if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0;
193
194 if(i2==0){
195 if( params[i2]->GetVarName() == "_System_LocalThis" ){
196 //オブジェクトメンバの第一パラメータのThisポインタ
197 continue;
198 }
199 }
200 if(i2==0||i2==1){
201 if( params[i2]->GetVarName() == lpszVarNameToReturn ){
202 //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト
203 continue;
204 }
205 }
206
207 Type dummyType;
208 BOOL bByVal;
209 if(bEllipse){
210 NumOpe_GetType( Parms[i2], Type(), dummyType );
211 bByVal=1;
212 }
213 else{
214 dummyType = *params[i2];
215 bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE;
216
217 // 型パラメータを解決
218 ResolveFormalGenericTypeParameter( dummyType, leftType, pUserProc );
219 }
220
221 if(bByVal==1){
222 //値参照
223/*
224 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
225 char temp2[255];
226 sprintf(temp2,"%s関数の第%dパラメータ",procName.c_str(),i2+1);
227 SetError(19,temp2,cp);
228 continue;
229 }
230*/
231 if( dummyType.IsStruct() ){
232 SetStructParameter( dummyType, Parms[i2] );
233 goto next;
234 }
235
236 BOOL bCalcUseHeap;
237 Type calcType;
238 if( !NumOpe( Parms[i2], dummyType, calcType, &bCalcUseHeap ) ){
239 break;
240 }
241
242 if( calcType.IsObject() ){
243 if( !dummyType.IsObject()
244 ||
245 dummyType.IsObject() &&
246 !dummyType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){
247 //キャスト演算子のオーバーロードに対応する
248 CallCastOperatorProc( calcType, bCalcUseHeap,dummyType );
249 }
250 }
251
252 if(!bEllipse){
253 //型チェック
254 // TODO: _System_ReturnValueが考慮されていない?
255 if(bHas_System_LocalThis) i3=i2-1;
256 else i3=i2;
257 CheckDifferentType(
258 dummyType,
259 calcType,
260 procName.c_str(),
261 i3);
262 }
263
264 if( dummyType.IsDouble() ){
265 ChangeTypeToDouble( calcType.GetBasicType() );
266 ParmSize+=sizeof(long)*2;
267 }
268 else if( dummyType.IsSingle() ){
269 ChangeTypeToSingle( calcType.GetBasicType() );
270 ParmSize+=sizeof(long);
271 }
272 else if( dummyType.Is64() ){
273 ChangeTypeToInt64( calcType.GetBasicType() );
274 ParmSize+=sizeof(long)*2;
275 }
276 else if( dummyType.IsLong() || dummyType.IsDWord()
277 || dummyType.IsPointer()
278 || dummyType.IsObject() || dummyType.IsStruct() ){
279 ChangeTypeToLong( calcType.GetBasicType() );
280 ParmSize+=sizeof(long);
281 }
282 else if( dummyType.IsInteger() || dummyType.IsWord() ){
283 ChangeTypeToInteger( calcType.GetBasicType() );
284 ParmSize+=sizeof(long);
285 }
286 else if( dummyType.IsSByte() || dummyType.IsByte() || dummyType.IsBoolean() ){
287 ChangeTypeToByte( calcType.GetBasicType() );
288 ParmSize+=sizeof(long);
289 }
290 else{
291 SetError(300,NULL,cp);
292 }
293 }
294 else{
295 //ポインタ参照
296 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
297 //ポインタ指定
298
299 Type calcType;
300 if( !NumOpe( Parms[i2]+2, dummyType, calcType) ){
301 break;
302 }
303
304 ChangeTypeToLong( calcType.GetBasicType() );
305
306 dummyType.PtrLevelUp();
307
308 //型チェック
309 if(bHas_System_LocalThis) i3=i2-1;
310 else i3=i2;
311 CheckDifferentType(
312 dummyType,
313 calcType,
314 procName.c_str(),
315 i3);
316 }
317 else{
318 if( useTempParameters[i2] ){
319 //一時オブジェクトをコピー
320
321 if( !types[i2].IsStruct() ){
322 // 一時参照のための領域を考慮する
323 nCountOfNowTempObjects++;
324 }
325
326 nCountOfNowTempObjects++;
327
328 //mov eax, dword ptr[esp+offset]
329 compiler.codeGenerator.op_mov_RM(
330 sizeof(long),
331 REG_EAX,
332 REG_ESP,
333 ( ( ParmsNum - i2 - 1 ) + ( nCountOfTempObjects - nCountOfNowTempObjects ) ) * PTR_SIZE,
334 MOD_BASE_DISP32 );
335
336 //push eax
337 compiler.codeGenerator.op_push(REG_EAX);
338 }
339 else{
340 //変数のアドレスを取得
341 Type varType;
342 if(GetVarOffset(
343 false,
344 false,
345 Parms[i2],
346 &RelativeVar,
347 varType)){
348 if( !dummyType.IsAny() ){
349 //型チェックを行う
350 if( dummyType.GetBasicType() == varType.GetBasicType() ){
351 if( dummyType.IsObject() ){
352 if( !dummyType.GetClass().IsEqualsOrSubClass( &varType.GetClass() ) ){
353 SetError(11,Parms[i2],cp);
354 }
355 }
356 else if( dummyType.IsStruct() ){
357 if( !dummyType.GetClass().IsEquals( &varType.GetClass() ) ){
358 SetError(11,Parms[i2],cp);
359 }
360 }
361 }
362 else if( (varType.GetBasicType()&FLAG_PTR)
363 &&((varType.GetBasicType()^FLAG_PTR)==dummyType.GetBasicType())){
364 //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき
365 }
366 else{
367 SetError(11,Parms[i2],cp);
368 }
369 }
370
371 //変数アドレスをレジスタにセット
372 SetVarPtrToEax(&RelativeVar);
373
374 //push eax
375 compiler.codeGenerator.op_push(REG_EAX);
376 }
377 }
378 }
379
380 ParmSize+=PTR_SIZE;
381 }
382
383next:;
384 }
385
386 return ParmSize;
387}
Note: See TracBrowser for help on using the repository browser.