source: dev/BasicCompiler32/Compile_Var.cpp @ 131

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

Prototypeクラスを用意した。

File size: 31.9 KB
Line 
1#include "../BasicCompiler_Common/common.h"
2#include "Opcode.h"
3
4//変数
5Variables globalVars;
6int AllGlobalVarSize;
7int AllInitGlobalVarSize;
8
9int AllLocalVarSize;
10
11
12void SetRelativeOffset( Type &resultType, RELATIVE_VAR *pRelativeVar,const char *lpPtrOffset){
13    PushLongVariable(pRelativeVar);
14
15    Type type;
16    NumOpe( lpPtrOffset, Type(), type );
17    ChangeTypeToLong( type.GetBasicType() );
18
19    //pop ebx
20    op_pop(REG_EBX);
21
22    if( resultType.PtrLevel() ){
23        resultType.PtrLevelDown();
24
25        int typeSize = resultType.GetSize();
26        if(typeSize>=2){
27            //imul ebx,i2
28            op_imul_RV( REG_EBX, typeSize );
29        }
30    }
31    else{
32        //エラー
33        SetError(1,NULL,cp);
34        return;
35    }
36
37    //pop ecx
38    op_pop(REG_ECX);
39
40    //add ecx,ebx
41    OpBuffer[obp++]=(char)0x03;
42    OpBuffer[obp++]=(char)0xCB;
43}
44void SetRelativeOffset( RELATIVE_VAR &relativeVar ){
45    if(relativeVar.dwKind==VAR_DIRECTMEM){
46        //mov ecx,dword ptr[ecx]
47        op_mov_RM( sizeof(long), REG_ECX, REG_ECX, 0, MOD_BASE );
48    }
49    else{
50        //直接参照に切り替え
51        SetVarPtrToEax(&relativeVar);
52        relativeVar.dwKind=VAR_DIRECTMEM;
53
54        //mov ecx,dword ptr[eax]
55        op_mov_RM( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
56    }
57}
58bool GetArrayOffset(const int *SubScripts,char *array, const Type &type){
59    extern HANDLE hHeap;
60    int i,i2,i3,i4;
61    char temporary[VN_SIZE],*pParm[MAX_PARMS];
62
63    for(i=0,i2=0,i3=0;;i++,i2++){
64        if(array[i]=='('){
65            i4=GetStringInPare(temporary+i2,array+i);
66            i+=i4-1;
67            i2+=i4-1;
68            continue;
69        }
70        if(array[i]=='['){
71            i4=GetStringInBracket(temporary+i2,array+i);
72            i+=i4-1;
73            i2+=i4-1;
74            continue;
75        }
76        if(array[i]==','||array[i]=='\0'){
77            if(SubScripts[i3]==-1){
78                for(i3--;i3>=0;i3--) HeapDefaultFree(pParm[i3]);
79                return 0;
80            }
81
82            temporary[i2]=0;
83
84            pParm[i3]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
85            lstrcpy(pParm[i3],temporary);
86
87            i3++;
88
89            if(array[i]=='\0'){
90                if(SubScripts[i3]!=-1){
91                    for(i3--;i3>=0;i3--) HeapDefaultFree(pParm[i3]);
92                    return 0;
93                }
94                break;
95            }
96
97            i2=-1;
98            continue;
99        }
100        temporary[i2]=array[i];
101    }
102
103    //push ecx
104    op_push(REG_ECX);
105
106    //push 0
107    op_push_V(0);
108
109    for(i=i3-1;i>=0;i--){
110        Type tempType;
111        BOOL bUseHeap;
112        NumOpe( pParm[i], Type( DEF_LONG ), tempType, &bUseHeap );
113        if( tempType.IsObject() ){
114            //キャスト演算子のオーバーロードに対応する
115            CallCastOperatorProc(
116                tempType,
117                bUseHeap, Type(DEF_LONG) );
118            tempType.SetBasicType( DEF_LONG );
119        }
120        ChangeTypeToLong( tempType.GetBasicType() );
121
122        //pop eax
123        op_pop(REG_EAX);
124
125        for(i2=i+1,i4=1;i2<i3;i2++) i4*=SubScripts[i2]+1;
126
127        //imul eax,i4
128        OpBuffer[obp++]=(char)0x69;
129        OpBuffer[obp++]=(char)0xC0;
130        *((long *)(OpBuffer+obp))=i4;
131        obp+=sizeof(long);
132
133        //add dword ptr[esp],eax
134        OpBuffer[obp++]=(char)0x01;
135        OpBuffer[obp++]=(char)0x04;
136        OpBuffer[obp++]=(char)0x24;
137
138        HeapDefaultFree(pParm[i]);
139    }
140
141    //pop eax
142    op_pop(REG_EAX);
143
144    //imul eax,TypeSize
145    OpBuffer[obp++]=(char)0x69;
146    OpBuffer[obp++]=(char)0xC0;
147    *((long *)(OpBuffer+obp)) = type.GetSize();
148    obp+=sizeof(long);
149
150    //pop ecx
151    op_pop(REG_ECX);
152
153    //add ecx,eax
154    OpBuffer[obp++]=(char)0x03;
155    OpBuffer[obp++]=(char)0xC8;
156
157    return 1;
158}
159bool _member_offset(bool isErrorEnabled, bool isWriteAccess, const CClass &objClass, const char *member, RELATIVE_VAR *pRelativeVar, Type &resultType, BOOL bPrivateAccess){
160    int i;
161
162
163    //////////////////////////////////////
164    // クラス、配列の構成要素を解析する
165    //////////////////////////////////////
166
167    char VarName[VN_SIZE];      //変数名
168    char array[VN_SIZE];        //第1次配列
169    char lpPtrOffset[VN_SIZE];  //第2次配列
170    char NestMember[VN_SIZE];   //入れ子メンバ
171    CClass::RefType refType;
172    lstrcpy(VarName,member);
173    if(!GetVarFormatString(VarName,array,lpPtrOffset,NestMember,refType)) return false;
174
175
176    ////////////////////////////
177    // メンバオフセットを取得
178    ////////////////////////////
179
180    int offset = objClass.GetMemberOffset( VarName, &i );
181    if(i==objClass.iMemberNum){
182        if(isErrorEnabled) SetError(103,VarName,cp);
183        return false;
184    }
185
186    CMember *pMember=objClass.ppobj_Member[i];
187
188
189    //アクセシビリティをチェック
190    if(&objClass==pobj_CompilingClass){
191        //同一クラスオブジェクトの場合はプライベートアクセスを容認する
192        if(pMember->dwAccess==ACCESS_NON){
193            if(isErrorEnabled) SetError(107,VarName,cp);
194            return false;
195        }
196    }
197    else{
198        if((bPrivateAccess==0&&pMember->dwAccess==ACCESS_PRIVATE)||
199            pMember->dwAccess==ACCESS_NON){
200            if(isErrorEnabled) SetError(107,VarName,cp);
201            return false;
202        }
203        else if(bPrivateAccess==0&&pMember->dwAccess==ACCESS_PROTECTED){
204            if(isErrorEnabled) SetError(108,VarName,cp);
205            return false;
206        }
207    }
208
209    //Const定義の場合は書き込みアクセスを制限する
210    //※コンストラクタをコンパイル中の場合は例外的に許可する
211    if( pMember->IsConst() &&       //定数メンバである
212        isWriteAccess &&                            //書き込みアクセスを要求されている
213        objClass.IsCompilingConstructor() == false  //コンストラクタ コンパイル中を除く
214        ){
215            //Const定義の変数に書き込みアクセスをしようとした場合
216            SetError(61,VarName,cp);
217    }
218
219    resultType = *pMember;
220
221    //ポインタ変数の場合
222    if( resultType.IsPointer() ){
223        if(pMember->SubScripts[0]==-1){
224            lstrcpy(lpPtrOffset,array);
225            array[0]=0;
226        }
227    }
228    else{
229        if(lpPtrOffset[0]){
230            if(isErrorEnabled) SetError(16,member,cp);
231            return false;
232        }
233    }
234
235    if(offset){
236        //add ecx,offset
237        OpBuffer[obp++]=(char)0x81;
238        OpBuffer[obp++]=(char)0xC1;
239        *((long *)(OpBuffer+obp))=offset;
240        obp+=sizeof(long);
241    }
242
243    if(array[0]){
244        //配列オフセット
245        if(!GetArrayOffset(pMember->SubScripts,array,*pMember)){
246            if(isErrorEnabled) SetError(14,member,cp);
247        }
248    }
249    else if(pMember->SubScripts[0]!=-1){
250        resultType.SetBasicType( resultType.GetBasicType() | FLAG_PTR );
251    }
252
253    if(NestMember[0]){
254        //入れ子構造の場合
255
256        if( resultType.IsObject() || resultType.IsStruct() ){
257            if( refType != CClass::Dot ){
258                if(isErrorEnabled) SetError(104,member,cp);
259                return false;
260            }
261
262            if( resultType.IsObject() ){
263                // 参照内容へのポインタを抽出
264                SetRelativeOffset( *pRelativeVar );
265            }
266        }
267        else if( resultType.IsObjectPtr() || resultType.IsStructPtr() ){
268            //構造体ポインタ型メンバ変数
269
270            if(lpPtrOffset[0]){
271                //pObj[n].member
272                if( ( resultType.IsObjectPtr() || resultType.IsStructPtr() )
273                    && refType != CClass::Dot ){
274                        if(isErrorEnabled) SetError(104,member,cp);
275                        return false;
276                }
277
278                //直接参照に切り替え
279                SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
280                pRelativeVar->dwKind=VAR_DIRECTMEM;
281
282                lpPtrOffset[0]=0;
283            }
284            else{
285                //pObj->member
286                if( ( resultType.IsObjectPtr() || resultType.IsStructPtr() )
287                    && refType != CClass::Pointer ){
288                        if(isErrorEnabled) SetError(104,member,cp);
289                        return false;
290                }
291
292                SetRelativeOffset( *pRelativeVar );
293            }
294        }
295        else if( resultType.GetBasicType() == MAKE_PTR_TYPE(DEF_OBJECT,2)
296            || resultType.GetBasicType() == MAKE_PTR_TYPE(DEF_STRUCT,2)){
297            //構造体ポインタのポインタ型メンバ変数
298
299            if(lpPtrOffset[0]){
300                //ppObj[n]->member
301                if( refType != CClass::Pointer ){
302                    if(isErrorEnabled) SetError(104,member,cp);
303                    return false;
304                }
305
306                //直接参照に切り替え
307                SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
308                pRelativeVar->dwKind=VAR_DIRECTMEM;
309
310                lpPtrOffset[0]=0;
311
312                //mov ecx,dword ptr[ecx]
313                OpBuffer[obp++]=(char)0x8B;
314                OpBuffer[obp++]=(char)0x09;
315            }
316            else{
317                if(isErrorEnabled) SetError(104,member,cp);
318                return false;
319            }
320        }
321
322        if(!_member_offset(
323            isErrorEnabled,
324            isWriteAccess,
325            pMember->GetClass(),
326            NestMember,
327            pRelativeVar,
328            resultType,
329            0)) return false;
330    }
331
332    if(lpPtrOffset[0]){
333        SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
334        pRelativeVar->dwKind=VAR_DIRECTMEM;
335    }
336
337    return true;
338}
339
340int LocalVar_ThisPtrOffset;
341void SetThisPtrToReg(int reg){
342    //自身のオブジェクトのThisポインタをregにコピー
343
344    RELATIVE_VAR RelativeVar;
345    RelativeVar.dwKind=VAR_LOCAL;
346    RelativeVar.bOffsetOffset=0;
347    RelativeVar.offset=-LocalVar_ThisPtrOffset;
348
349    SetReg_WholeVariable(DEF_PTR_VOID,&RelativeVar,reg);
350}
351
352bool GetVarOffset(bool isErrorEnabled,bool isWriteAccess,const char *NameBuffer,RELATIVE_VAR *pRelativeVar,Type &resultType,int *pss){
353    int i;
354    char variable[VN_SIZE];
355
356    if(NameBuffer[0]=='.'){
357        GetWithName(variable);
358        lstrcat(variable,NameBuffer);
359    }
360    else lstrcpy(variable,NameBuffer);
361
362    // 名前空間を分離
363    char namespaceStr[VN_SIZE]="", simpleName[VN_SIZE];
364    Smoothie::Meta::namespaceScopesCollection.SplitNamespace( variable, namespaceStr, simpleName );
365
366    // 先頭オブジェクトまたはクラス名と入れ子メンバに分割
367    CClass::RefType refType;
368    char member[VN_SIZE],array[VN_SIZE],lpPtrOffset[VN_SIZE];
369    GetVarFormatString(simpleName,array,lpPtrOffset,member,refType);
370
371    // 名前空間を分離していた場合は結合
372    char VarName[VN_SIZE];
373    if( namespaceStr[0] ){
374        sprintf( VarName, "%s.%s", namespaceStr, simpleName );
375    }
376    else{
377        lstrcpy( VarName, simpleName );
378    }
379
380    const int *pSubScripts;
381    bool bConst = false;
382
383
384    if( UserProc::IsLocalAreaCompiling() ){
385        //////////////////
386        // ローカル変数
387        //////////////////
388
389        const Variable *pVar = UserProc::CompilingUserProc().localVars.BackSearch( VarName );
390        if( pVar ){
391            //ポインタ変数の場合
392            if( pVar->IsPointer() ){
393                if( !pVar->IsArray() ){
394                    lstrcpy(lpPtrOffset,array);
395                    array[0]=0;
396                }
397            }
398            else{
399                if(lpPtrOffset[0]){
400                    SetError(16,variable,cp);
401                    pRelativeVar->dwKind=NON_VAR;
402                    return false;
403                }
404            }
405
406            pRelativeVar->offset=-pVar->offset;
407            pRelativeVar->bOffsetOffset=0;
408            if( pVar->IsRef() ){
409                // 参照型
410                pRelativeVar->dwKind = VAR_REFLOCAL;
411            }
412            else pRelativeVar->dwKind=VAR_LOCAL;
413            resultType = *pVar;
414            pSubScripts=pVar->GetSubScriptsPtr();
415            bConst = pVar->IsConst();
416
417            goto ok;
418        }
419    }
420
421    if(pobj_CompilingClass){
422        //////////////////////
423        // クラスメンバの参照
424        //////////////////////
425
426        if(lstrcmpi(variable,"This")==0){
427            //Thisオブジェクト
428
429            //Thisポインタをecxにコピー
430            SetThisPtrToReg(REG_ECX);
431
432            pRelativeVar->dwKind=VAR_DIRECTMEM;
433
434            resultType.SetType( DEF_OBJECT, pobj_CompilingClass );
435            return true;
436        }
437
438        if(memicmp(variable,"This.",5)==0){
439            //Thisオブジェクトのメンバを参照するとき
440            SlideString(variable+5,-5);
441            lstrcpy(VarName,variable);
442        }
443        else{
444            //クラス内メンバを参照するとき(通常)
445
446            for(i=0;i<pobj_CompilingClass->iMemberNum;i++){
447                if(lstrcmp(VarName,pobj_CompilingClass->ppobj_Member[i]->name)==0) break;
448            }
449            if(i==pobj_CompilingClass->iMemberNum) goto NonClassMember;
450        }
451
452        //Const修飾子のメソッド内でメンバ書き込みアクセスが発生したとき
453        //(コンストラクタ、デストラクタ内を除く)
454        CMethod *pMethod = pobj_DBClass->GetNowCompilingMethodInfo();
455        if( isWriteAccess &&
456            pMethod->isConst &&
457            pobj_CompilingClass->IsCompilingConstructor() == false &&
458            pobj_CompilingClass->IsCompilingDestructor() == false
459            ){
460                SetError(131, NULL, cp );
461        }
462
463        /////////////////////////////
464        // thisポインタをecxにセット
465
466        //Thisポインタをecxにコピー
467        SetThisPtrToReg(REG_ECX);
468
469        pRelativeVar->dwKind=VAR_DIRECTMEM;
470        if(!_member_offset(
471            isErrorEnabled,
472            isWriteAccess,
473            *pobj_CompilingClass,
474            variable,
475            pRelativeVar,
476            resultType,1)) return false;
477        return true;
478    }
479
480NonClassMember:
481
482    {
483        const Variable *pVar;
484
485        //////////////////////////
486        // 静的ローカル変数
487        // ※"Static.Object.Method.Variable"
488        //////////////////////////
489
490        char temporary[VN_SIZE];
491        if( UserProc::IsLocalAreaCompiling() ){
492            GetNowStaticVarFullName(VarName,temporary);
493
494            pVar = globalVars.Find( temporary );
495            if( pVar ){
496                goto GlobalOk;
497            }
498        }
499
500
501        //////////////////////////
502        // クラスの静的メンバ
503        //////////////////////////
504
505        if(member[0]){
506            lstrcpy(temporary,member);
507
508            // TODO: 名前空間を考慮したコードになっていない
509
510            char tempMember[VN_SIZE];
511            char tempArray[VN_SIZE];
512            {
513                CClass::RefType refType;
514                GetVarFormatString(temporary,tempArray,lpPtrOffset,tempMember, refType );
515            }
516
517            int typeDefIndex = Smoothie::Meta::typeDefs.GetIndex( VarName );
518            if( typeDefIndex != -1 ){
519                // TypeDef後の型名だったとき
520                lstrcpy( VarName, Smoothie::Meta::typeDefs[typeDefIndex].GetBaseName().c_str() );
521            }
522
523            char temp2[VN_SIZE];
524            sprintf(temp2,"%s.%s",VarName,temporary);
525            pVar = globalVars.Find( temp2 );
526            if( pVar ){
527                lstrcpy(member,tempMember);
528                lstrcpy(array,tempArray);
529                goto GlobalOk;
530            }
531        }
532
533        if(pobj_CompilingClass){
534            //自身のクラスから静的メンバを参照する場合
535            char temp2[VN_SIZE];
536            sprintf(temp2,"%s.%s",pobj_CompilingClass->GetName().c_str(),VarName);
537            pVar = globalVars.Find( temp2 );
538            if( pVar ){
539                goto GlobalOk;
540            }
541        }
542
543        /////////////////////
544        // グローバル変数
545        /////////////////////
546
547        pVar = globalVars.BackSearch( VarName );
548        if( pVar ){
549            goto GlobalOk;
550        }
551
552        if(isErrorEnabled) SetError(3,variable,cp);
553        pRelativeVar->dwKind=NON_VAR;
554        return false;
555
556
557
558GlobalOk:
559        //ポインタ変数の場合
560        if( pVar->IsPointer() ){
561            if( !pVar->IsArray() ){
562                lstrcpy(lpPtrOffset,array);
563                array[0]=0;
564            }
565        }
566        else{
567            if(lpPtrOffset[0]){
568                SetError(16,variable,cp);
569                pRelativeVar->dwKind=NON_VAR;
570                return false;
571            }
572        }
573
574        pRelativeVar->offset=pVar->offset;
575        pRelativeVar->bOffsetOffset=0;
576        if( pVar->IsRef() ){
577            // 参照型
578            pRelativeVar->dwKind = VAR_REFGLOBAL;
579        }
580        else pRelativeVar->dwKind=VAR_GLOBAL;
581        resultType = *pVar;
582        pSubScripts=pVar->GetSubScriptsPtr();
583        bConst = pVar->IsConst();
584    }
585
586
587
588ok:
589
590    if( bConst && isWriteAccess ){
591        //Const定義の変数に書き込みアクセスをしようとした場合
592        if( resultType.IsObject() ){
593            //オブジェクト定数
594            SetError(130, VarName, cp );
595        }
596        else{
597            //一般のConst変数
598            SetError(61,VarName,cp);
599        }
600    }
601
602    if(array[0]==0&&pSubScripts[0]!=-1){
603        //配列の先頭ポインタを示す場合
604        resultType.SetBasicType( resultType.GetBasicType() | FLAG_PTR );
605        if(pss) memcpy(pss,pSubScripts,MAX_ARRAYDIM);
606        return true;
607    }
608
609    if(array[0]||member[0]){
610        //xor ecx,ecx(ecxを0に初期化する)
611        //※ecxは変数ベースアドレスからの相対オフセットを示す
612        op_zero_reg(REG_ECX);
613
614        pRelativeVar->bOffsetOffset=1;
615    }
616    if(array[0]){
617        if(!GetArrayOffset(pSubScripts,array,resultType)){
618            SetError(14,variable,cp);
619            pRelativeVar->dwKind=NON_VAR;
620            return false;
621        }
622    }
623    if(member[0]){
624        if( resultType.IsObject() || resultType.IsStruct() ){
625            //実態オブジェクトのメンバを参照(obj.member)
626            if( refType != CClass::Dot ){
627                SetError(104,VarName,cp);
628                pRelativeVar->dwKind=NON_VAR;
629                return false;
630            }
631
632            if( resultType.IsObject() ){
633                // 参照内容へのポインタを抽出
634                SetRelativeOffset( *pRelativeVar );
635            }
636        }
637        else if( resultType.IsObjectPtr() || resultType.IsStructPtr() ){
638            //ポインタオブジェクトが示すメンバを参照
639            if(lpPtrOffset[0]){
640                //pObj[n].member
641                if( refType != CClass::Dot ){
642                    SetError(104,VarName,cp);
643                    pRelativeVar->dwKind=NON_VAR;
644                    return false;
645                }
646                SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
647                pRelativeVar->dwKind=VAR_DIRECTMEM;
648            }
649            else{
650                //pObj->member
651                if( refType != CClass::Pointer ){
652                    SetError(104,VarName,cp);
653                    pRelativeVar->dwKind=NON_VAR;
654                    return false;
655                }
656
657                SetVarPtrToEax(pRelativeVar);
658                pRelativeVar->dwKind=VAR_DIRECTMEM;
659
660                //mov ecx,dword ptr[eax]
661                OpBuffer[obp++]=(char)0x8B;
662                OpBuffer[obp++]=(char)0x08;
663            }
664        }
665        else if( resultType.GetBasicType()==MAKE_PTR_TYPE(DEF_OBJECT,2) || resultType.GetBasicType()==MAKE_PTR_TYPE(DEF_STRUCT,2)){
666            //ポインタオブジェクトが示すメンバを参照
667            if(lpPtrOffset[0]){
668                //ppObj[n]->member
669                if( refType != CClass::Pointer ){
670                    SetError(104,VarName,cp);
671                    pRelativeVar->dwKind=NON_VAR;
672                    return false;
673                }
674
675                SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
676                pRelativeVar->dwKind=VAR_DIRECTMEM;
677
678
679                SetVarPtrToEax(pRelativeVar);
680
681                //mov ecx,dword ptr[eax]
682                OpBuffer[obp++]=(char)0x8B;
683                OpBuffer[obp++]=(char)0x08;
684            }
685            else{
686                SetError(104,VarName,cp);
687                pRelativeVar->dwKind=NON_VAR;
688                return false;
689            }
690        }
691        else{
692            SetError(102,VarName,cp);
693            pRelativeVar->dwKind=NON_VAR;
694            return false;
695        }
696
697        if(!_member_offset(
698            isErrorEnabled,
699            isWriteAccess,
700            resultType.GetClass(),
701            member,pRelativeVar,resultType,0)) return false;
702
703        return true;
704    }
705
706    if(lpPtrOffset[0]){
707        SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset);
708        pRelativeVar->dwKind=VAR_DIRECTMEM;
709    }
710
711    return true;
712}
713
714bool SetInitGlobalData(int offset,const Type &type,const int *SubScripts,char *InitBuf){
715    extern BYTE *initGlobalBuf;
716    int i,i2,i3;
717    char temporary[VN_SIZE];
718
719    if(InitBuf[0]=='['){
720        SlideString(InitBuf+1,-1);
721        InitBuf[lstrlen(InitBuf)-1]=0;
722
723        int typeSize = type.GetSize();
724
725        if(SubScripts[0]!=-1){
726            typeSize*=JumpSubScripts(SubScripts+1);
727            i=0;
728            i2=0;
729            while(1){
730                if(SubScripts[0]<i2){
731                    SetError(41,0,cp);
732                    return 0;
733                }
734                i=GetOneParameter(InitBuf,i,temporary);
735                if(!SetInitGlobalData(
736                    offset+i2*typeSize,
737                    type,
738                    SubScripts+1,
739                    temporary)) return false;
740                i2++;
741                if(InitBuf[i]=='\0') break;
742            }
743            return true;
744        }
745
746        if(type.IsStruct()){
747            const CClass &objClass = type.GetClass();
748
749            for(i=0,i2=0;i2<objClass.iMemberNum;i2++){
750                i=GetOneParameter(InitBuf,i,temporary);
751
752                i3=objClass.GetMemberOffset( objClass.ppobj_Member[i2]->name, NULL );
753
754                if(!SetInitGlobalData(offset+i3,
755                    *objClass.ppobj_Member[i2],
756                    objClass.ppobj_Member[i2]->SubScripts,
757                    temporary)) return false;
758
759                if(InitBuf[i]=='\0') break;
760            }
761            if(i2+1!=objClass.iMemberNum){
762                SetError(41,0,cp);
763                return false;
764            }
765            return true;
766        }
767
768        SetError(41,0,cp);
769        return false;
770    }
771
772
773    ///////////////////////////////////////
774    // 単発式([]で囲まれていない)
775    ///////////////////////////////////////
776
777    if( type.IsObject() || type.IsStruct() ){
778        //オブジェクトまたは構造体の場合はありえない
779        SetError(300,NULL,cp);
780        return false;
781    }
782
783    if(SubScripts[0]!=-1){
784        SetError(41,0,cp);
785        return false;
786    }
787
788    double dbl;
789    _int64 i64data;
790    Type calcType;
791
792    if( !StaticCalculation(false, InitBuf,type.GetBasicType(),&i64data,calcType) ){
793        //動的データだった場合
794        return false;
795    }
796    if( calcType.IsReal() ){
797        memcpy(&dbl,&i64data,sizeof(double));
798        i64data=(_int64)dbl;
799    }
800    else dbl=(double)i64data;
801
802    //型チェック
803    CheckDifferentType(
804        type,
805        calcType,
806        0,0);
807
808    if( type.IsDouble() ){
809        *(double *)(initGlobalBuf+offset)=(double)dbl;
810    }
811    else if( type.IsSingle() ){
812        *(float *)(initGlobalBuf+offset)=(float)dbl;
813    }
814    else if( type.Is64() ){
815        *(_int64 *)(initGlobalBuf+offset)=i64data;
816    }
817    else if( type.IsLong() || type.IsDWord() || type.IsPointer() ){
818        if(type.GetBasicType()==typeOfPtrChar){
819            //文字列定数のとき
820
821            char *temp;
822            temp=(char *)i64data;
823            i2=dataTable.AddString(temp,lstrlen(temp));
824            HeapDefaultFree(temp);
825
826            //mov eax,DataPos
827            OpBuffer[obp++]=(char)0xB8;
828            *((long *)(OpBuffer+obp))=(long)i2;
829            pobj_DataTableSchedule->add();
830            obp+=sizeof(long);
831
832            //mov dword ptr[offset],eax
833            OpBuffer[obp++]=(char)0xA3;
834            *((long *)(OpBuffer+obp))=offset;
835            pobj_GlobalVarSchedule->add();
836            obp+=sizeof(long);
837        }
838        else{
839            *(DWORD *)(initGlobalBuf+offset)=(DWORD)i64data;
840        }
841    }
842    else if( type.IsWord() || type.IsInteger() ){
843        *(WORD *)(initGlobalBuf+offset)=(WORD)i64data;
844    }
845    else if( type.IsSByte() || type.IsByte() || type.IsBoolean() ){
846        *(BYTE *)(initGlobalBuf+offset)=(BYTE)i64data;
847    }
848
849    return true;
850}
851bool InitLocalVar(int offset,const Type &type,const int *SubScripts,char *InitBuf){
852    int i,i2,i3;
853    char temporary[VN_SIZE];
854
855    if(InitBuf[0]=='['){
856        SlideString(InitBuf+1,-1);
857        InitBuf[lstrlen(InitBuf)-1]=0;
858
859        int typeSize = type.GetSize();
860
861        if(SubScripts[0]!=-1){
862            typeSize*=JumpSubScripts(SubScripts+1);
863            i=0;
864            i2=0;
865            while(1){
866                if(SubScripts[0]<i2){
867                    SetError(41,0,cp);
868                    return false;
869                }
870                i=GetOneParameter(InitBuf,i,temporary);
871                if(!InitLocalVar(
872                    offset+i2*typeSize,
873                    type,
874                    SubScripts+1,
875                    temporary)) return false;
876                i2++;
877                if(InitBuf[i]=='\0') break;
878            }
879            return true;
880        }
881
882        if(type.IsStruct()){
883            const CClass &objClass = type.GetClass();
884
885            for(i=0,i2=0;i2<objClass.iMemberNum;i2++){
886                i=GetOneParameter(InitBuf,i,temporary);
887
888                i3=objClass.GetMemberOffset( objClass.ppobj_Member[i2]->name, NULL );
889
890                if(!InitLocalVar(offset+i3,
891                    *objClass.ppobj_Member[i2],
892                    objClass.ppobj_Member[i2]->SubScripts,
893                    temporary)) return false;
894
895                if(InitBuf[i]=='\0') break;
896            }
897            if(i2+1!=objClass.iMemberNum){
898                SetError(41,0,cp);
899                return 0;
900            }
901            return true;
902        }
903
904        SetError(41,0,cp);
905        return false;
906    }
907
908
909    ///////////////////////////////////////
910    // 単発式([]で囲まれていない)
911    ///////////////////////////////////////
912
913    if(SubScripts[0]!=-1){
914        SetError(41,0,cp);
915        return false;
916    }
917
918    double dbl;
919    _int64 i64data;
920    Type calcType;
921
922    if( !StaticCalculation(false, InitBuf,type.GetBasicType(),&i64data,calcType) ){
923        //動的データだった場合
924        return false;
925    }
926    if( calcType.IsReal() ){
927        memcpy(&dbl,&i64data,sizeof(double));
928        i64data=(_int64)dbl;
929    }
930    else dbl=(double)i64data;
931
932    //型チェック
933    CheckDifferentType(
934        type,
935        calcType,
936        0,0);
937
938    if( type.IsDouble() ){
939        //mov eax,HILONG(dbl)
940        OpBuffer[obp++]=(char)0xB8;
941        *((long *)(OpBuffer+obp))=(long)*(long *)(((char *)(&dbl))+4);
942        obp+=sizeof(long);
943
944        //mov dword ptr[ebp+offset+sizeof(long)],eax
945        OpBuffer[obp++]=(char)0x89;
946        OpBuffer[obp++]=(char)0x85;
947        *((long *)(OpBuffer+obp))=offset+sizeof(long);
948        AddLocalVarAddrSchedule();
949        obp+=sizeof(long);
950
951        //mov eax,LOLONG(dbl)
952        OpBuffer[obp++]=(char)0xB8;
953        *((long *)(OpBuffer+obp))=*(long *)(&dbl);
954        obp+=sizeof(long);
955
956        //mov dword ptr[ebp+offset],eax
957        OpBuffer[obp++]=(char)0x89;
958        OpBuffer[obp++]=(char)0x85;
959        *((long *)(OpBuffer+obp))=offset;
960        AddLocalVarAddrSchedule();
961        obp+=sizeof(long);
962    }
963    else if( type.IsSingle() ){
964        float flt;
965        flt=(float)dbl;
966        //mov eax,InitValue
967        OpBuffer[obp++]=(char)0xB8;
968        *((long *)(OpBuffer+obp))=*(long *)&flt;
969        obp+=sizeof(long);
970
971        //mov dword ptr[ebp+offset],eax
972        OpBuffer[obp++]=(char)0x89;
973        OpBuffer[obp++]=(char)0x85;
974        *((long *)(OpBuffer+obp))=offset;
975        AddLocalVarAddrSchedule();
976        obp+=sizeof(long);
977    }
978    else if( type.Is64() ){
979        //mov eax,HILONG(i64data)
980        OpBuffer[obp++]=(char)0xB8;
981        *((long *)(OpBuffer+obp))=(long)*(long *)(((char *)(&i64data))+4);
982        obp+=sizeof(long);
983
984        //mov dword ptr[ebp+offset+sizeof(long)],eax
985        OpBuffer[obp++]=(char)0x89;
986        OpBuffer[obp++]=(char)0x85;
987        *((long *)(OpBuffer+obp))=offset+sizeof(long);
988        AddLocalVarAddrSchedule();
989        obp+=sizeof(long);
990
991        //mov eax,LOLONG(i64data)
992        OpBuffer[obp++]=(char)0xB8;
993        *((long *)(OpBuffer+obp))=*(long *)(&i64data);
994        obp+=sizeof(long);
995
996        //mov dword ptr[ebp+offset],eax
997        OpBuffer[obp++]=(char)0x89;
998        OpBuffer[obp++]=(char)0x85;
999        *((long *)(OpBuffer+obp))=offset;
1000        AddLocalVarAddrSchedule();
1001        obp+=sizeof(long);
1002    }
1003    else if( type.IsDWord() || type.IsLong() || type.IsPointer() ){
1004        if(type.GetBasicType()==typeOfPtrChar){
1005            //文字列定数のとき
1006
1007            char *temp;
1008            temp=(char *)i64data;
1009            i2=dataTable.AddString(temp,lstrlen(temp));
1010            HeapDefaultFree(temp);
1011
1012            //mov eax,DataPos
1013            OpBuffer[obp++]=(char)0xB8;
1014            *((long *)(OpBuffer+obp))=(long)i2;
1015            pobj_DataTableSchedule->add();
1016            obp+=sizeof(long);
1017        }
1018        else{
1019            //mov eax,InitValue
1020            OpBuffer[obp++]=(char)0xB8;
1021            *((long *)(OpBuffer+obp))=(long)i64data;
1022            obp+=sizeof(long);
1023        }
1024
1025        //mov dword ptr[ebp+offset],eax
1026        OpBuffer[obp++]=(char)0x89;
1027        OpBuffer[obp++]=(char)0x85;
1028        *((long *)(OpBuffer+obp))=offset;
1029        AddLocalVarAddrSchedule();
1030        obp+=sizeof(long);
1031    }
1032    else if( type.IsWord() || type.IsInteger() ){
1033        //mov ax,InitValue
1034        OpBuffer[obp++]=(char)0x66;
1035        OpBuffer[obp++]=(char)0xB8;
1036        *((WORD *)(OpBuffer+obp))=(WORD)i64data;
1037        obp+=sizeof(WORD);
1038
1039        //mov word ptr[ebp+offset],ax
1040        OpBuffer[obp++]=(char)0x66;
1041        OpBuffer[obp++]=(char)0x89;
1042        OpBuffer[obp++]=(char)0x85;
1043        *((long *)(OpBuffer+obp))=offset;
1044        AddLocalVarAddrSchedule();
1045        obp+=sizeof(long);
1046    }
1047    else if( type.IsSByte() || type.IsByte() || type.IsBoolean() ){
1048        //mov byte ptr[ebp+offset],InitValue
1049        OpBuffer[obp++]=(char)0xC6;
1050        OpBuffer[obp++]=(char)0x85;
1051        *((long *)(OpBuffer+obp))=offset;
1052        AddLocalVarAddrSchedule();
1053        obp+=sizeof(long);
1054        *((BYTE *)(OpBuffer+obp))=(BYTE)i64data;
1055        obp+=sizeof(BYTE);
1056    }
1057
1058    return true;
1059}
1060
1061void dim( char *VarName,int *SubScripts,Type &type,char *InitBuf,char *ConstractParameter,DWORD dwFlags){
1062    if( UserProc::IsGlobalAreaCompiling() ){
1063        /////////////////////////
1064        // グローバル変数
1065        /////////////////////////
1066
1067        AddGlobalVariable(VarName,SubScripts,type,InitBuf,ConstractParameter,dwFlags);
1068    }
1069    else{
1070        /////////////////
1071        // ローカル変数
1072        /////////////////
1073
1074        if( UserProc::CompilingUserProc().localVars.DuplicateCheck( VarName ) ){
1075            //2重定義のエラー
1076            SetError(15,VarName,cp);
1077            return;
1078        }
1079
1080        bool isConst = ( dwFlags & DIMFLAG_CONST ) ? true:false;
1081
1082        Variable *pVar = new Variable( VarName, type, isConst );
1083
1084        if( SubScripts[0] != -1 ){
1085            //配列あり
1086            pVar->SetArray( SubScripts );
1087        }
1088
1089        //コンストラクタ用パラメータ
1090        pVar->paramStrForConstructor = ConstractParameter;
1091
1092        //レキシカルスコープ
1093        pVar->ScopeLevel=obj_LexScopes.GetNowLevel();
1094        pVar->ScopeStartAddress=obj_LexScopes.GetStartAddress();
1095        pVar->bLiving=TRUE;
1096
1097        //エラー用
1098        pVar->source_code_address=cp;
1099
1100        // 変数を追加
1101        UserProc::CompilingUserProc().localVars.push_back( pVar );
1102
1103        //アラインメントを考慮
1104        if( pVar->IsStruct() ){
1105            int alignment = pVar->GetClass().iAlign;
1106
1107            if( alignment ){
1108                if( AllLocalVarSize % alignment ){
1109                    AllLocalVarSize += alignment - (AllLocalVarSize % alignment);
1110                }
1111            }
1112
1113            if( alignment == PTR_SIZE*2 ){
1114                // ポインタに要するサイズよりも一回り大きなアラインメントが指定されているとき
1115                // (例:CONTEXT構造体など)
1116                // 呼び出し側のオフセットズレを考慮する
1117
1118                if( 0 == ( UserProc::CompilingUserProc().RealParams().GetMemorySize() + PTR_SIZE/*ret分*/ ) % alignment ){
1119                    AllLocalVarSize += PTR_SIZE;
1120                }
1121            }
1122        }
1123
1124        AllLocalVarSize += pVar->GetMemorySize();
1125        pVar->offset = AllLocalVarSize;
1126
1127        //レキシカルスコープ
1128        pVar->ScopeLevel=obj_LexScopes.GetNowLevel();
1129        pVar->ScopeStartAddress=obj_LexScopes.GetStartAddress();
1130        pVar->bLiving=TRUE;
1131
1132        if(InitBuf[0]){
1133            //初期代入時のみ、書き込みアクセスを許可する
1134            if( isConst ){
1135                pVar->ConstOff();
1136            }
1137
1138            int result = 0;
1139            if( !pVar->IsObject() ){
1140                result = InitLocalVar(-pVar->offset,
1141                    *pVar,
1142                    pVar->GetSubScriptsPtr(),
1143                    InitBuf);
1144            }
1145
1146            if(!result){
1147                //動的な式だった場合は代入演算を行う
1148                char temporary[8192];
1149                sprintf(temporary,"%s=%s",VarName,InitBuf);
1150                OpcodeCalc(temporary);
1151            }
1152
1153            if( isConst ){
1154                pVar->ConstOn();
1155            }
1156        }
1157        else{
1158            //push 0
1159            op_push_V(0);
1160
1161            //push VarSize
1162            op_push_V( pVar->GetMemorySize() );
1163
1164            //mov eax,ebp
1165            OpBuffer[obp++]=(char)0x8B;
1166            OpBuffer[obp++]=(char)0xC5;
1167
1168            //add eax,offset
1169            OpBuffer[obp++]=(char)0x05;
1170            *((long *)(OpBuffer+obp))=-pVar->offset;
1171            AddLocalVarAddrSchedule();
1172            obp+=sizeof(long);
1173
1174            //push eax
1175            op_push(REG_EAX);
1176
1177            //call FillMemory
1178            OpBuffer[obp++]=(char)0xFF;
1179            OpBuffer[obp++]=(char)0x15;
1180            DllProc *pDllProc = GetDeclareHash("FillMemory");
1181            pDllProc->Using();
1182            pobj_ImportAddrSchedule->add(pDllProc);
1183            obp+=sizeof(long);
1184        }
1185    }
1186
1187    //New呼び出し
1188    if( type.IsObject() &&(dwFlags&DIMFLAG_NONCALL_CONSTRACTOR)==0&&InitBuf[0]=='\0'){
1189        char objectSize[255];
1190        if( SubScripts[0] == -1 ){
1191            objectSize[0] = 0;
1192        }
1193        else{
1194            if( SubScripts[1] != -1 ){
1195                SetError(300,NULL,cp);
1196            }
1197            sprintf( objectSize, "%d", SubScripts[0] );
1198        }
1199        Operator_New( type.GetClass(), objectSize, ConstractParameter, type );
1200
1201        //pop eax
1202        op_pop( REG_EAX );
1203
1204        RELATIVE_VAR RelativeVar;
1205        GetVarOffset( true, false, VarName, &RelativeVar, Type() );
1206        if( RelativeVar.dwKind == VAR_DIRECTMEM ){
1207            SetError();
1208        }
1209        SetVariableFromEax( DEF_OBJECT, DEF_OBJECT, &RelativeVar );
1210    }
1211}
1212
1213void SetVarPtrToEax(RELATIVE_VAR *pRelativeVar){
1214    if(pRelativeVar->dwKind==VAR_GLOBAL){
1215        if(pRelativeVar->bOffsetOffset){
1216            //lea eax,dword ptr[ecx+offset]
1217            OpBuffer[obp++]=(char)0x8D;
1218            OpBuffer[obp++]=(char)0x81;
1219            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1220            pobj_GlobalVarSchedule->add();
1221            obp+=sizeof(long);
1222        }
1223        else{
1224            //mov eax,offset
1225            OpBuffer[obp++]=(char)0xB8;
1226            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1227            pobj_GlobalVarSchedule->add();
1228            obp+=sizeof(long);
1229        }
1230    }
1231    else if(pRelativeVar->dwKind==VAR_REFGLOBAL){
1232        if(pRelativeVar->bOffsetOffset){
1233            //mov eax,ecx
1234            OpBuffer[obp++]=(char)0x8B;
1235            OpBuffer[obp++]=(char)0xC1;
1236
1237            //add eax,dword ptr[offset]
1238            op_add_RM( sizeof(long), REG_EAX, REG_NON, (int)pRelativeVar->offset, MOD_DISP32 );
1239        }
1240        else{
1241            //mov eax,dword ptr[offset]
1242            op_mov_RM( sizeof(long), REG_EAX, REG_NON, (int)pRelativeVar->offset, MOD_DISP32 );
1243        }
1244        obp-=sizeof(long);
1245        pobj_GlobalVarSchedule->add();
1246        obp+=sizeof(long);
1247    }
1248    else if(pRelativeVar->dwKind==VAR_LOCAL){
1249        if(pRelativeVar->bOffsetOffset){
1250            //add ecx,offset
1251            OpBuffer[obp++]=(char)0x81;
1252            OpBuffer[obp++]=(char)0xC1;
1253            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1254            AddLocalVarAddrSchedule();
1255            obp+=sizeof(long);
1256
1257            //lea eax,dword ptr[ebp+ecx]
1258            OpBuffer[obp++]=(char)0x8D;
1259            OpBuffer[obp++]=(char)0x44;
1260            OpBuffer[obp++]=(char)0x0D;
1261            OpBuffer[obp++]=(char)0x00;
1262        }
1263        else{
1264            //lea eax,dword ptr[ebp+offset]
1265            OpBuffer[obp++]=(char)0x8D;
1266            OpBuffer[obp++]=(char)0x85;
1267            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1268            AddLocalVarAddrSchedule();
1269            obp+=sizeof(long);
1270        }
1271    }
1272    else if(pRelativeVar->dwKind==VAR_REFLOCAL){
1273        if(pRelativeVar->bOffsetOffset){
1274            //mov eax,ecx
1275            OpBuffer[obp++]=(char)0x8B;
1276            OpBuffer[obp++]=(char)0xC1;
1277
1278            //add eax,dword ptr[ebp+offset]
1279            OpBuffer[obp++]=(char)0x03;
1280            OpBuffer[obp++]=(char)0x85;
1281            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1282            AddLocalVarAddrSchedule();
1283            obp+=sizeof(long);
1284        }
1285        else{
1286            //mov eax,dword ptr[ebp+offset]
1287            OpBuffer[obp++]=(char)0x8B;
1288            OpBuffer[obp++]=(char)0x85;
1289            *((long *)(OpBuffer+obp))=pRelativeVar->offset;
1290            AddLocalVarAddrSchedule();
1291            obp+=sizeof(long);
1292        }
1293    }
1294    else if(pRelativeVar->dwKind==VAR_DIRECTMEM){
1295        //mov eax,ecx
1296        OpBuffer[obp++]=(char)0x8B;
1297        OpBuffer[obp++]=(char)0xC1;
1298    }
1299}
1300void SetVarPtrToReg(int reg,RELATIVE_VAR *pRelativeVar){
1301    if( reg != REG_EAX ){
1302        SetError();
1303        //TODO: 未完成
1304    }
1305    SetVarPtrToEax( pRelativeVar );
1306}
1307
1308bool Compile_AddGlobalRootsForGc(){
1309    UserProc *pUserProc_AddGlobalRootPtr = GetClassMethod( "_System_CGarbageCollection", "AddGlobalRootPtr" );
1310    if( !pUserProc_AddGlobalRootPtr ){
1311        SetError(3, "_System_CGarbageCollection.AddGlobalRootPtr", -1 );
1312        return false;
1313    }
1314
1315    BOOST_FOREACH( const Variable *pVar, globalVars ){
1316        if( pVar->IsObject() || pVar->IsPointer() || pVar->IsStruct() ){
1317            // オブジェクトまたはポインタだったとき
1318            // ※構造体も含む(暫定対応)
1319
1320            // 変数領域に要するLONG_PTR単位の個数を引き渡す
1321            op_push_V( pVar->GetMemorySize()/PTR_SIZE );
1322
1323
1324            /////////////////////////////
1325            // ルートポインタを引き渡す
1326
1327            //mov eax,offset
1328            op_mov_RV(REG_EAX,(int)pVar->offset);
1329            obp-=sizeof(long);
1330            pobj_GlobalVarSchedule->add();
1331            obp+=sizeof(long);
1332
1333            //push eax
1334            op_push( REG_EAX );
1335
1336            //
1337            /////////////////////////////
1338
1339
1340            /////////////////////////////
1341            // Thisポインタを引き渡す
1342
1343            SetThisPtrToReg(REG_EAX);
1344
1345            //push eax
1346            op_push( REG_EAX );
1347
1348            //
1349            /////////////////////////////
1350
1351
1352            // call AddGlobalRootPtr
1353            op_call( pUserProc_AddGlobalRootPtr );
1354
1355            ReallocNativeCodeBuffer();
1356        }
1357    }
1358
1359    return true;
1360}
Note: See TracBrowser for help on using the repository browser.