source: dev/trunk/ab5.0/abdev/BasicCompiler64/CParameter.cpp@ 452

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

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

File size: 12.5 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 int stackItemNum = 0;
16
17 useTempObject = false;
18
19 BOOL bEllipse;
20 if(params.size()){
21 if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1;
22 else bEllipse=0;
23 }
24 else bEllipse=0;
25
26 for(int i2=ParmsNum-1;i2>=0;i2--){
27 useTempParameters[i2] = false;
28
29 if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0;
30
31 if(i2==0){
32 if( params[i2]->GetVarName() == "_System_LocalThis" ){
33 //オブジェクトメンバの第一パラメータのThisポインタ
34 continue;
35 }
36 }
37 if( i2==0||i2==1 ){
38 if( params[i2]->GetVarName() == procName ){
39 //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト
40 continue;
41 }
42 }
43
44 Type dummyType;
45 BOOL bByVal;
46 if(bEllipse){
47 NumOpe_GetType( Parms[i2], Type(), dummyType );
48 bByVal=1;
49 }
50 else{
51 dummyType = *params[i2];
52 bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE;
53 }
54
55
56 if( !bByVal ){
57 //ポインタ参照
58 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
59 //ポインタ指定
60 continue;
61 }
62
63 if( !GetVarType( Parms[i2], Type(), FALSE ) ){
64 //変数ではないとき
65 int reg = REG_RAX;
66 Type calcType;
67 bool isNeedHeapFreeStructure;
68 NumOpe( &reg, Parms[i2], dummyType, calcType, &isNeedHeapFreeStructure );
69
70 if( !calcType.IsStruct() ){
71 //一時参照を作成
72 pobj_sf->push( reg );
73 pobj_sf->mov_sp( reg );
74
75 stackItemNum++;
76 }
77
78 //スタックフレームへコピー
79 StackOffsetOfTempObject[i2] = pobj_sf->push(reg);
80
81 stackItemNum++;
82
83 bool result = CheckDifferentType(
84 dummyType,
85 calcType,
86 procName.c_str(),
87 i2);
88
89 if( result )
90 {
91 useTempParameters[i2] = true;
92 isNeedFreeStructures[i2] = isNeedHeapFreeStructure;
93 useTempObject = true;
94
95 types[i2] = calcType;
96 }
97 }
98 }
99 }
100
101 return stackItemNum * PTR_SIZE;
102}
103void ParamImpl::DeleteTempParameters(){
104 ///////////////////////////////////////////////////////
105 // 一時オブジェクトを破棄
106 ///////////////////////////////////////////////////////
107 if( !useTempObject ) return;
108
109 for(int i2=ParmsNum-1;i2>=0;i2--){
110 if( useTempParameters[i2] ){
111 if( types[i2].IsStruct() ){
112 // 構造体の一時メモリ
113
114 if( isNeedFreeStructures[i2] )
115 {
116 //メモリを解放する
117
118 pobj_sf->pop( REG_RCX );
119
120 //call free
121 extern const UserProc *pSub_free;
122 compiler.codeGenerator.op_call(pSub_free);
123 }
124 else
125 {
126 pobj_sf->pop();
127 }
128 }
129 else
130 {
131 pobj_sf->pop();
132 pobj_sf->pop();
133 }
134 }
135 }
136}
137
138void ParamImpl::SetStructParameter( int reg, const Type &baseType, const char *expression ){
139 //////////////////////////////////////////////////////
140 ///// レジスタ資源のバックアップ
141 { BACKUP_REGISTER_RESOURCE
142 //////////////////////////////////////////////////////
143
144 int object_size = baseType.GetClass().GetSize();
145
146 //mov rcx,object_size
147 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RCX,object_size);
148
149 //call calloc
150 extern const UserProc *pSub_calloc;
151 compiler.codeGenerator.op_call(pSub_calloc);
152
153 //mov r11,rax
154 compiler.codeGenerator.op_mov_RR(REG_R11,REG_RAX);
155
156 //mov qword ptr[rsp+offset],r11 ※スタックフレームを利用
157 pobj_sf->push(REG_R11);
158
159
160 Type calcType;
161 bool isNeedHeapFreeStructure;
162 int temp_reg=REG_RAX;
163 NumOpe( &temp_reg,
164 expression,
165 baseType,
166 calcType,
167 &isNeedHeapFreeStructure );
168
169
170 //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用
171 pobj_sf->ref(REG_R11);
172
173
174 RELATIVE_VAR RelativeVar;
175 RelativeVar.bOffsetOffset=0;
176 RelativeVar.offset=0;
177 RelativeVar.dwKind=VAR_DIRECTMEM;
178
179 SetStructVariableFromRax(
180 baseType,
181 calcType,
182 &RelativeVar,isNeedHeapFreeStructure);
183
184
185 //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用
186 pobj_sf->pop(REG_R11);
187
188 /////////////////////////////////////////////
189 ////// レジスタ資源を復元
190 RESTORE_REGISTER_RESOURCE
191 }////////////////////////////////////////////
192
193 //mov reg,r11
194 compiler.codeGenerator.op_mov_RR(reg,REG_R11);
195}
196
197
198void ParamImpl::SetParameter( const string &procName, const Parameters &params, int SecondParmNum, const UserProc *pUserProc ){
199 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
200
201 ///////////////////////////////////////////////////////////
202 // パラメータをレジスタ及びスタックフレームにセット
203 ///////////////////////////////////////////////////////////
204 int i2,i3;
205
206 BOOL bEllipse;
207 if( params.size() ){
208 if(params[params.size()-1]->GetBasicType()==DEF_ELLIPSE) bEllipse=1;
209 else bEllipse=0;
210 }
211 else bEllipse=0;
212
213 BOOL bHas_System_LocalThis=0;
214 if(ParmsNum>=1){
215 if( params[0]->GetVarName() == "_System_LocalThis" ){
216 bHas_System_LocalThis=1;
217 }
218 }
219
220 //戻り値用の変数名を取得
221 const char *lpszVarNameToReturn = (procName[0]==1&&procName[1]==ESC_OPERATOR)?"_System_ReturnValue":procName.c_str();
222
223 //パラメータをレジスタとスタックに格納
224 int ParmSize=0;
225 int reg,temp_reg;
226 RELATIVE_VAR RelativeVar;
227 for(i2=ParmsNum-1;i2>=0;i2--){
228 if(bEllipse&&i2<=(int)params.size()-2) bEllipse=0;
229
230 if(i2==0){
231 if( params[i2]->GetVarName() == "_System_LocalThis" ){
232 //オブジェクトメンバの第一パラメータのThisポインタ
233 continue;
234 }
235 }
236 if(i2==0||i2==1){
237 if( params[i2]->GetVarName() == lpszVarNameToReturn ){
238 //オブジェクトメンバの第一または第二パラメータの戻り値用オブジェクト
239 continue;
240 }
241 }
242
243 Type dummyType;
244 BOOL bByVal;
245 if(bEllipse){
246 NumOpe_GetType( Parms[i2], Type(), dummyType );
247 bByVal=1;
248 }
249 else{
250 dummyType = *params[i2];
251 bByVal = ( params[i2]->IsRef() == false ) ? TRUE:FALSE;
252
253 // 型パラメータを解決
254 ResolveFormalGenericTypeParameter( dummyType, leftType, pUserProc );
255 }
256
257 int xmm_temp_sw=0;
258 if(dummyType.IsReal()&&bByVal){
259 //実数型
260 if(i2==0) reg=REG_XMM0;
261 else if(i2==1) reg=REG_XMM1;
262 else if(i2==2) reg=REG_XMM2;
263 else if(i2==3) reg=REG_XMM3;
264 else{
265 reg=REG_XMM0;
266 xmm_temp_sw=1;
267 }
268 }
269 else{
270 //整数型
271 if(i2==0) reg=REG_RCX;
272 else if(i2==1) reg=REG_RDX;
273 else if(i2==2) reg=REG_R8;
274 else if(i2==3) reg=REG_R9;
275 else reg=REG_RAX;
276 }
277
278 if(bByVal==1){
279 //値参照
280
281 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
282 char temp2[255];
283 sprintf(temp2,"%s関数の第%dパラメータ",procName,i2+1);
284 SetError(19,temp2,cp);
285 continue;
286 }
287
288 if( dummyType.IsStruct() ){
289 SetStructParameter( reg, dummyType, Parms[i2] );
290 goto next;
291 }
292
293 temp_reg=reg;
294
295 Type calcType;
296 bool isNeedHeapFreeStructure;
297 if( !NumOpe( &temp_reg, Parms[i2], dummyType, calcType, &isNeedHeapFreeStructure ) ){
298 break;
299 }
300
301 if( calcType.IsObject() ){
302 if( !dummyType.IsObject()
303 ||
304 dummyType.IsObject() &&
305 !dummyType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){
306 //キャスト演算子のオーバーロードに対応する
307 CallCastOperatorProc( reg, calcType, isNeedHeapFreeStructure,dummyType );
308 }
309 }
310
311
312 if(bEllipse){
313 if( calcType.IsReal() ){
314 //整数レジスタへコピー
315 //※cdeclの拡張パラメータは実数の場合も汎用レジスタで引渡し
316
317 if(0<=i2&&i2<=3){
318 if(i2==0) reg=REG_RCX;
319 else if(i2==1) reg=REG_RDX;
320 else if(i2==2) reg=REG_R8;
321 else if(i2==3) reg=REG_R9;
322
323 //movd reg,temp_reg
324 compiler.codeGenerator.op_movd_RX(reg,temp_reg);
325 }
326 }
327 else if( calcType.IsWhole() ){
328 //整数型の場合は、64ビットへ拡張する
329 ExtendTypeTo64( calcType.GetBasicType(), temp_reg );
330 }
331 }
332 else{
333 //型チェック
334 // TODO: _System_ReturnValueが考慮されていない?
335 if(bHas_System_LocalThis) i3=i2-1;
336 else i3=i2;
337 CheckDifferentType(
338 dummyType,
339 calcType,
340 procName.c_str(),
341 i3);
342
343 if( dummyType.IsDouble() ){
344 //Double型へ変換
345 ChangeTypeToXmm_Double(calcType.GetBasicType(),reg,temp_reg);
346 }
347 else if( dummyType.IsSingle() ){
348 //Single型へ変換
349 ChangeTypeToXmm_Single(calcType.GetBasicType(),reg,temp_reg);
350 }
351 else if( dummyType.IsWhole() ){
352 //実数型 → 整数型
353 ChangeTypeToWhole(calcType,dummyType,reg,temp_reg);
354 }
355 }
356 }
357 else{
358 //ポインタ参照
359 if(Parms[i2][0]==1&&Parms[i2][1]==ESC_BYVAL){
360 //ポインタ指定
361
362 temp_reg=reg;
363 Type calcType;
364 if( !NumOpe(&temp_reg, Parms[i2]+2, dummyType, calcType) ){
365 break;
366 }
367
368 dummyType.PtrLevelUp();
369
370 //型チェック
371 if(bHas_System_LocalThis) i3=i2-1;
372 else i3=i2;
373 CheckDifferentType(
374 dummyType,
375 calcType,
376 procName.c_str(),
377 i3);
378
379 if( calcType.IsReal() ){
380 //実数型 → 整数型
381 ChangeTypeToWhole( calcType, Type(DEF_QWORD), reg, temp_reg );
382 }
383 }
384 else{
385 if( useTempParameters[i2] ){
386 //一時オブジェクトをコピー
387
388 //mov reg, qword ptr[rsp+offset]
389 pobj_sf->ref_offset_data( reg, StackOffsetOfTempObject[i2] );
390 }
391 else{
392 //変数のアドレスを取得
393 Type varType;
394 if(GetVarOffset(
395 false,
396 false,
397 Parms[i2],
398 &RelativeVar,
399 varType)){
400
401 if( !dummyType.IsAny() ){
402 //型チェックを行う
403 if( dummyType.GetBasicType() == varType.GetBasicType() ){
404 if( dummyType.IsObject() ){
405 if( !dummyType.GetClass().IsEqualsOrSubClass( &varType.GetClass() ) ){
406 SetError(11,Parms[i2],cp);
407 }
408 }
409 else if( dummyType.IsStruct() ){
410 if( !dummyType.GetClass().IsEquals( &varType.GetClass() ) ){
411 SetError(11,Parms[i2],cp);
412 }
413 }
414 }
415 else if( (varType.GetBasicType()&FLAG_PTR)
416 &&((varType.GetBasicType()^FLAG_PTR)==dummyType.GetBasicType())){
417 //仮引数がポインタ参照で、実引数が配列の先頭ポインタのとき
418 }
419 else{
420 SetError(11,Parms[i2],cp);
421 }
422 }
423
424 //変数アドレスをレジスタにセット
425 SetVarPtrToReg(reg,&RelativeVar);
426
427 }
428 }
429 }
430 }
431
432next:
433
434 if(reg==REG_RAX){
435 //スタックフレームへコピー
436 //mov qword ptr[rsp+offset],rax
437 compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32);
438 }
439 else if(xmm_temp_sw){
440 //スタックフレームへコピー
441
442 //movlpd qword ptr[rsp+offset],xmm0
443 compiler.codeGenerator.op_movlpd_MR(REG_XMM0,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32);
444 }
445
446
447 /////////////////////
448 // レジスタをロック
449 /////////////////////
450
451 if(0<=i2&&i2<=3){
452 // ※rcx, rdx, r8, r9の場合のみ
453 pobj_BlockReg->lock(reg);
454 }
455 }
456
457 //パラメータが収まるだけのスタックフレームを確保
458 pobj_sf->parameter_allocate((int)params.size()*sizeof(_int64)+ sizeof(_int64)/*ret用*/ );
459}
460void ParamImpl::BackupParameter(int pi_num){
461 ///////////////////////////////////////////////////////////
462 // スタックフレームに存在する既存のパラメータをバックアップ
463 ///////////////////////////////////////////////////////////
464 int i2;
465
466 for(i2=0;i2<ParmsNum;i2++){
467 /////////////////////
468 // バックアップ
469 /////////////////////
470
471 extern CDBLockParms obj_DBLockParms;
472 if(obj_DBLockParms.array_LevelCount[i2]){
473 //mov r14,qword ptr[rsp+offset]
474 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R14,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32);
475
476 //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用
477 pobj_sf->push(REG_R14);
478 }
479
480 if(3<i2){
481 //スタックフレームをロック
482 extern CDBLockParms obj_DBLockParms;
483 obj_DBLockParms.lock(i2);
484 }
485 }
486}
487void ParamImpl::RestoreParameter(int pi_num){
488 ///////////////////////////////////////////////////////////
489 // スタックフレームに存在する既存のパラメータを復元
490 ///////////////////////////////////////////////////////////
491 int i2;
492
493 for(i2=ParmsNum-1;i2>=0;i2--){
494 /////////////////////
495 // 復元
496 /////////////////////
497
498 if(3<i2){
499 //スタックフレームをアンロック
500 extern CDBLockParms obj_DBLockParms;
501 obj_DBLockParms.unlock(i2);
502 }
503
504 extern CDBLockParms obj_DBLockParms;
505 if(obj_DBLockParms.array_LevelCount[i2]){
506 //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用
507 pobj_sf->pop(REG_R14);
508
509 //mov qword ptr[rsp+offset],r14
510 compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_R14,REG_RSP,i2*sizeof(_int64),MOD_BASE_DISP32);
511 }
512 }
513}
Note: See TracBrowser for help on using the repository browser.