source: dev/trunk/abdev/BasicCompiler64/CParameter.cpp@ 366

Last change on this file since 366 was 331, checked in by dai_9181, 17 years ago

AddressOfの左辺値を加味した処理を簡潔にした

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