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
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
[75]8int ParamImpl::NewTempParameters( const string &procName, const Parameters &params, int SecondParmNum ){
9 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[20]10
[73]11 ///////////////////////////////////////////////////////
12 // 一時オブジェクトをあらかじめスタックに積んでおく
13 ///////////////////////////////////////////////////////
[64]14
[73]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
[76]45 Type dummyType;
[73]46 BOOL bByVal;
47 if(bEllipse){
[76]48 NumOpe_GetType( Parms[i2], Type(), dummyType );
[73]49 bByVal=1;
50 }
51 else{
[76]52 dummyType = *params[i2];
[73]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
[76]64 if( !GetVarType( Parms[i2], Type(), FALSE ) ){
[73]65 //変数ではないとき
[76]66 Type calcType;
[435]67 BOOL bUseHeap;
68 NumOpe( Parms[i2], dummyType, calcType, &bUseHeap );
[73]69 //↑ここでスタックに積む
70
71 nCountOfTempObjects++;
72
[76]73 if( !calcType.IsStruct() ){
[73]74 //一時参照を作成
75
76 //push esp
[225]77 compiler.codeGenerator.op_push( REG_ESP );
[73]78
79 nCountOfTempObjects++;
80 }
81
82 bool result = CheckDifferentType(
[76]83 dummyType,
84 calcType,
[75]85 procName.c_str(),
[73]86 i2);
87
[435]88 if( result && bUseHeap ){
[73]89 useTempParameters[i2] = true;
90 useTempObject = true;
91
[76]92 types[i2] = calcType;
[73]93 }
94 }
95 }
96 }
97
98 return nCountOfTempObjects * PTR_SIZE;
99}
100
[71]101void ParamImpl::DeleteTempParameters(){
[20]102 ///////////////////////////////////////////////////////
103 // 一時オブジェクトを破棄
104 ///////////////////////////////////////////////////////
105 if( !useTempObject ) return;
106
107 for(int i2=ParmsNum-1;i2>=0;i2--){
108 if( useTempParameters[i2] ){
[76]109 if( types[i2].IsStruct() ){
[64]110 // 構造体の一時メモリ
[20]111
[64]112 //メモリを解放する
[20]113
[64]114 //call free
[206]115 extern const UserProc *pSub_free;
[225]116 compiler.codeGenerator.op_call(pSub_free);
[45]117 }
[64]118 else{
[76]119 if( types[i2].Is64() ){
[66]120 //pop ... 参照を消す
121 //pop ... 上位32ビット
122 //pop ... 下位32ビット
[225]123 compiler.codeGenerator.op_add_esp( PTR_SIZE * 3 );
[66]124 }
125 else{
126 //pop ... 参照を消す
127 //pop ... 値を消す
[225]128 compiler.codeGenerator.op_add_esp( PTR_SIZE * 2 );
[66]129 }
[64]130 }
[20]131 }
132 }
133}
134
[76]135void ParamImpl::SetStructParameter( const Type &baseType, const char *expression ){
136 int object_size = baseType.GetClass().GetSize();
[3]137
138 //push object_size
[225]139 compiler.codeGenerator.op_push_V(object_size);
[3]140
141 //call calloc
[206]142 extern const UserProc *pSub_calloc;
[225]143 compiler.codeGenerator.op_call(pSub_calloc);
[3]144
[76]145 //push eax(ここでプッシュされた値が実際にパラメータとして引き渡される)
[225]146 compiler.codeGenerator.op_push(REG_EAX);
[76]147
[3]148 //push eax
[225]149 compiler.codeGenerator.op_push(REG_EAX);
[3]150
[76]151 Type calcType;
152 BOOL bUseHeap;
153 NumOpe( expression,
154 baseType,
155 calcType,
156 &bUseHeap );
[3]157
[76]158 // ※スタックにある二つのデータ(コピー先、コピー元)の値を必要とする
159 SetStructVariable( baseType, calcType, bUseHeap );
[3]160}
161
[301]162int ParamImpl::SetParameter( const string &procName, const Parameters &params, int SecondParmNum, const UserProc *pUserProc ){
[75]163 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[3]164
[73]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 //戻り値用の変数名を取得
[75]185 const char *lpszVarNameToReturn = (procName[0]==1&&procName[1]==ESC_OPERATOR)?"_System_ReturnValue":procName.c_str();
[73]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
[76]207 Type dummyType;
[73]208 BOOL bByVal;
209 if(bEllipse){
[76]210 NumOpe_GetType( Parms[i2], Type(), dummyType );
[73]211 bByVal=1;
212 }
213 else{
[76]214 dummyType = *params[i2];
215 bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE;
[292]216
[299]217 // 型パラメータを解決
[301]218 ResolveFormalGenericTypeParameter( dummyType, leftType, pUserProc );
[73]219 }
220
221 if(bByVal==1){
222 //値参照
[284]223/*
[73]224 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
225 char temp2[255];
[283]226 sprintf(temp2,"%s関数の第%dパラメータ",procName.c_str(),i2+1);
[73]227 SetError(19,temp2,cp);
228 continue;
229 }
[284]230*/
[76]231 if( dummyType.IsStruct() ){
232 SetStructParameter( dummyType, Parms[i2] );
[73]233 goto next;
234 }
235
[76]236 BOOL bCalcUseHeap;
237 Type calcType;
238 if( !NumOpe( Parms[i2], dummyType, calcType, &bCalcUseHeap ) ){
239 break;
240 }
[73]241
[76]242 if( calcType.IsObject() ){
243 if( !dummyType.IsObject()
[73]244 ||
[76]245 dummyType.IsObject() &&
246 !dummyType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){
[73]247 //キャスト演算子のオーバーロードに対応する
[76]248 CallCastOperatorProc( calcType, bCalcUseHeap,dummyType );
[73]249 }
250 }
251
252 if(!bEllipse){
253 //型チェック
[76]254 // TODO: _System_ReturnValueが考慮されていない?
[73]255 if(bHas_System_LocalThis) i3=i2-1;
256 else i3=i2;
257 CheckDifferentType(
[76]258 dummyType,
259 calcType,
[75]260 procName.c_str(),
[73]261 i3);
262 }
263
[76]264 if( dummyType.IsDouble() ){
265 ChangeTypeToDouble( calcType.GetBasicType() );
[73]266 ParmSize+=sizeof(long)*2;
267 }
[76]268 else if( dummyType.IsSingle() ){
269 ChangeTypeToSingle( calcType.GetBasicType() );
[73]270 ParmSize+=sizeof(long);
271 }
[76]272 else if( dummyType.Is64() ){
273 ChangeTypeToInt64( calcType.GetBasicType() );
[73]274 ParmSize+=sizeof(long)*2;
275 }
[76]276 else if( dummyType.IsLong() || dummyType.IsDWord()
277 || dummyType.IsPointer()
278 || dummyType.IsObject() || dummyType.IsStruct() ){
279 ChangeTypeToLong( calcType.GetBasicType() );
280 ParmSize+=sizeof(long);
[73]281 }
[76]282 else if( dummyType.IsInteger() || dummyType.IsWord() ){
283 ChangeTypeToInteger( calcType.GetBasicType() );
[73]284 ParmSize+=sizeof(long);
285 }
[76]286 else if( dummyType.IsSByte() || dummyType.IsByte() || dummyType.IsBoolean() ){
287 ChangeTypeToByte( calcType.GetBasicType() );
[73]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
[76]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);
[73]316 }
317 else{
318 if( useTempParameters[i2] ){
319 //一時オブジェクトをコピー
320
[76]321 if( !types[i2].IsStruct() ){
[73]322 // 一時参照のための領域を考慮する
323 nCountOfNowTempObjects++;
324 }
325
326 nCountOfNowTempObjects++;
[3]327
[20]328 //mov eax, dword ptr[esp+offset]
[225]329 compiler.codeGenerator.op_mov_RM(
[20]330 sizeof(long),
331 REG_EAX,
332 REG_ESP,
[64]333 ( ( ParmsNum - i2 - 1 ) + ( nCountOfTempObjects - nCountOfNowTempObjects ) ) * PTR_SIZE,
[20]334 MOD_BASE_DISP32 );
[3]335
[20]336 //push eax
[225]337 compiler.codeGenerator.op_push(REG_EAX);
[64]338 }
339 else{
340 //変数のアドレスを取得
[76]341 Type varType;
[64]342 if(GetVarOffset(
343 false,
344 false,
345 Parms[i2],
346 &RelativeVar,
[76]347 varType)){
348 if( !dummyType.IsAny() ){
[64]349 //型チェックを行う
[76]350 if( dummyType.GetBasicType() == varType.GetBasicType() ){
351 if( dummyType.IsObject() ){
352 if( !dummyType.GetClass().IsEqualsOrSubClass( &varType.GetClass() ) ){
[64]353 SetError(11,Parms[i2],cp);
354 }
355 }
[76]356 else if( dummyType.IsStruct() ){
357 if( !dummyType.GetClass().IsEquals( &varType.GetClass() ) ){
[64]358 SetError(11,Parms[i2],cp);
359 }
360 }
361 }
[76]362 else if( (varType.GetBasicType()&FLAG_PTR)
363 &&((varType.GetBasicType()^FLAG_PTR)==dummyType.GetBasicType())){
[64]364 //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき
365 }
366 else{
367 SetError(11,Parms[i2],cp);
368 }
369 }
[20]370
[64]371 //変数アドレスをレジスタにセット
372 SetVarPtrToEax(&RelativeVar);
373
374 //push eax
[225]375 compiler.codeGenerator.op_push(REG_EAX);
[64]376 }
[20]377 }
[3]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.