source: dev/trunk/ab5.0/abdev/compiler_x86/CParameter.cpp@ 673

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

不正なByValに対するエラーメッセージが正確に表示されなくなるバグを修正

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