Changeset 34 in dev for BasicCompiler_Common


Ignore:
Timestamp:
Jan 14, 2007, 6:11:23 AM (18 years ago)
Author:
dai_9181
Message:

スコープ処理を統一した。関数の途中でReturnしても、スコープにあるローカルオブジェクトを正確に破棄できるようにした。

Location:
BasicCompiler_Common
Files:
1 added
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • BasicCompiler_Common/Compile.cpp

    r26 r34  
    1414LABEL *pLabelNames;
    1515int MaxLabelNum;
    16 
    17 //ループごとのスケジュール
    18 DWORD *pExitWhileSchedule;  //ExitWhileスケジュール
    19 int ExitWhileScheduleNum;
    20 DWORD *pExitForSchedule;    //ExitForスケジュール
    21 int ExitForScheduleNum;
    22 DWORD *pExitDoSchedule;     //ExitDoスケジュール
    23 int ExitDoScheduleNum;
    2416
    2517//Continueアドレス
     
    176168                break;
    177169            case ESC_EXITWHILE:
    178                 OpcodeExitWhile();
     170                obj_LexScopes.ExitWhile();
    179171                break;
    180172            case ESC_EXITFOR:
    181                 OpcodeExitFor();
     173                obj_LexScopes.ExitFor();
    182174                break;
    183175            case ESC_EXITDO:
    184                 OpcodeExitDo();
     176                obj_LexScopes.ExitDo();
    185177                break;
    186178            case ESC_CONTINUE:
  • BasicCompiler_Common/LexicalScoping.cpp

    r5 r34  
    99CLexicalScopes obj_LexScopes;
    1010
     11
     12CScope::CScope( int level, int addr, SCOPE_TYPE TypeOfStatement ){
     13    this->level = level;
     14    this->StartAddress = addr;
     15    this->TypeOfStatement = TypeOfStatement;
     16
     17    pBreakSchedule = (DWORD *)malloc( 1 );
     18    nBreakSchedule = 0;
     19}
     20CScope::~CScope(){
     21    free( pBreakSchedule );
     22}
     23
     24int CScope::GetStartAddress(){
     25    return StartAddress;
     26}
     27SCOPE_TYPE CScope::GetTypeOfStatement(){
     28    return TypeOfStatement;
     29}
     30
     31void CScope::Break(){
     32    //未解放のローカルオブジェクトを解放する
     33    obj_LexScopes.CallDestructorsOfReturn( level );
     34
     35    //jmp ...(Next addr)
     36    OpBuffer[obp++]=(char)0xE9;
     37
     38    pBreakSchedule=(DWORD *)realloc( pBreakSchedule, ( nBreakSchedule + 1 ) * sizeof(DWORD) );
     39    pBreakSchedule[nBreakSchedule]=obp;
     40    nBreakSchedule++;
     41
     42    obp+=sizeof(long);
     43}
     44void CScope::RunScheduleOfBreak(){
     45    for(int i=0;i<nBreakSchedule;i++){
     46        *((long *)(OpBuffer+pBreakSchedule[i]))=obp-(pBreakSchedule[i]+sizeof(long));
     47    }
     48}
     49
     50
     51CScope *CLexicalScopes::SearchScope( SCOPE_TYPE TypeOfStatement ){
     52    for( int i = level; i>=0; i-- ){
     53        if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){
     54            return ppScopes[i];
     55        }
     56    }
     57    return NULL;
     58}
     59
    1160CLexicalScopes::CLexicalScopes(){
     61    ppScopes = (CScope **)malloc( 1 );
    1262    level=0;
    1363}
    1464CLexicalScopes::~CLexicalScopes(){
     65    free( ppScopes );
    1566}
    1667void CLexicalScopes::Init(int addr){
    17     level=0;
    18     StartAddresses[level]=addr;
    19 }
    20 void CLexicalScopes::LevelUp(int addr){
     68    // TODO: エラーチェック
     69
     70    level = -1;
     71    Start( addr, SCOPE_TYPE_BASE );
     72}
     73void CLexicalScopes::Start( int addr, SCOPE_TYPE TypeOfStatement ){
    2174    level++;
    22     StartAddresses[level]=addr;
    23 }
    24 void CLexicalScopes::LevelDown(void){
    25     //デストラクタを呼ぶ
    26     CallDestrouctorsOfScope();
    27 
    28     //スコープレベルを下げる
    29     level--;
    30     if(level<0){
     75    ppScopes = (CScope **)realloc( ppScopes, ( level + 1 ) * sizeof( CScope * ) );
     76    ppScopes[level] = new CScope( level, addr, TypeOfStatement );
     77}
     78void CLexicalScopes::End(){
     79    if( level <= 0 ){
    3180        SetError(300,NULL,cp);
    3281        return;
    3382    }
     83
     84    //デストラクタを呼ぶ
     85    CallDestructorsOfScopeEnd();
    3486
    3587    extern BOOL bCompilingGlobal;
     
    51103    }
    52104
     105    //使用済みローカル変数の生存チェックを外す
    53106    for(int i=0;i<num;i++){
    54         if(pVar[i].bLiving&&pVar[i].ScopeLevel==level+1){
     107        if(pVar[i].bLiving&&pVar[i].ScopeLevel==level){
    55108            pVar[i].bLiving=0;
    56109            extern int obp;
     
    58111        }
    59112    }
    60 }
    61 
    62 int CLexicalScopes::GetNowLevel(void){
     113
     114
     115    //スコープ抜け出しスケジュール
     116    ppScopes[level]->RunScheduleOfBreak();
     117
     118
     119    //スコープレベルを下げる
     120    delete ppScopes[level];
     121    level--;
     122}
     123
     124void CLexicalScopes::ExitFor(){
     125    CScope *pScope = SearchScope( SCOPE_TYPE_FOR );
     126    if( !pScope ){
     127        SetError(12,"Exit For",cp);
     128        return;
     129    }
     130
     131    pScope->Break();
     132}
     133void CLexicalScopes::ExitWhile(){
     134    CScope *pScope = SearchScope( SCOPE_TYPE_WHILE );
     135    if( !pScope ){
     136        SetError(12,"Exit While",cp);
     137        return;
     138    }
     139
     140    pScope->Break();
     141}
     142void CLexicalScopes::ExitDo(){
     143    CScope *pScope = SearchScope( SCOPE_TYPE_DO );
     144    if( !pScope ){
     145        SetError(12,"Exit Do",cp);
     146        return;
     147    }
     148
     149    pScope->Break();
     150}
     151
     152int CLexicalScopes::GetNowLevel(){
    63153    return level;
    64154}
    65 int CLexicalScopes::GetStartAddress(void){
    66     return StartAddresses[level];
    67 }
     155void CLexicalScopes::SetNowLevel( int level ){
     156    this->level = level;
     157}
     158int CLexicalScopes::GetStartAddress(){
     159    return ppScopes[level]->GetStartAddress();
     160}
     161
     162
     163// スコープ終了時のデストラクタ呼び出し
     164void CLexicalScopes::CallDestructorsOfScopeEnd(){
     165    extern BOOL bCompilingGlobal;
     166    VARIABLE *pVar;
     167    int num;
     168    if(bCompilingGlobal){
     169        //グローバルオブジェクトの解放処理
     170        extern VARIABLE *GlobalVar;
     171        extern int MaxGlobalVarNum;
     172        pVar=GlobalVar;
     173        num=MaxGlobalVarNum;
     174    }
     175    else{
     176        //ローカルオブジェクトの解放処理
     177        extern VARIABLE *LocalVar;
     178        extern int MaxLocalVarNum;
     179        pVar=LocalVar;
     180        num=MaxLocalVarNum;
     181    }
     182
     183
     184    int i3,i4,i5;
     185    int indexSystemGC=-1;
     186    for( i3 = num - 1; i3 >= 0; i3-- ){     //確保したのと逆順序で解放するため、バックサーチにする
     187
     188        if( bCompilingGlobal && GetNowLevel() == 0 ){
     189            if(lstrcmp(pVar[i3].name,"_System_GC")==0){
     190                indexSystemGC=i3;
     191                continue;
     192            }
     193        }
     194
     195        //同一レベルのレキシカルスコープのみを検知
     196        if(!pVar[i3].bLiving) continue;
     197        if( pVar[i3].ScopeLevel != GetNowLevel() ) continue;
     198
     199        if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef&OBJECT_PARAMETER){
     200            //実態オブジェクトのパラメータを持つとき
     201
     202            //デストラクタを呼び出す
     203            i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
     204            if(i5!=-1)
     205                Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
     206
     207            //メモリを解放する
     208
     209#ifdef _AMD64_
     210            //x64ビットコード
     211
     212            //mov rcx,qword ptr[rsp+offset]
     213            op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
     214                -pVar[i3].offset,
     215                MOD_BASE_DISP32);
     216            obp-=sizeof(long);
     217            AddLocalVarAddrSchedule();
     218            obp+=sizeof(long);
     219#else
     220            //x86コード
     221
     222            //mov ecx,dword ptr[ebp+offset]
     223            op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32);
     224            obp-=sizeof(long);
     225            AddLocalVarAddrSchedule();
     226            obp+=sizeof(long);
     227
     228            //push ecx
     229            op_push(REG_ECX);
     230#endif
     231
     232            //call free
     233            extern SUBINFO *pSub_free;
     234            op_call(pSub_free);
     235
     236
     237            if(bCompilingGlobal){
     238                //ここには来ないハズ
     239                SetError(300,NULL,cp);
     240            }
     241        }
     242        else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){
     243            //デストラクタの呼び出し
     244            i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
     245            if(i5!=-1){
     246                int ss[MAX_ARRAYDIM];
     247                memset(ss,0,MAX_ARRAYDIM*sizeof(int));
     248                if(pVar[i3].SubScripts[0]!=-1){
     249                    while(1){
     250                        for(i4=0;;i4++){
     251                            if(pVar[i3].SubScripts[i4]==-1) break;
     252
     253                            if(ss[i4]>pVar[i3].SubScripts[i4]){
     254                                ss[i4]=0;
     255                                ss[i4+1]++;
     256                            }
     257                            else break;
     258                        }
     259                        if(pVar[i3].SubScripts[i4]==-1) break;
     260                        char temporary[VN_SIZE];
     261                        sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]);
     262                        for(i4=1;;i4++){
     263                            if(pVar[i3].SubScripts[i4]==-1) break;
     264
     265                            sprintf(temporary+lstrlen(temporary),",%d",ss[i4]);
     266                        }
     267                        lstrcat(temporary,"]");
     268                        Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,temporary,DEF_OBJECT);
     269
     270                        ss[0]++;
     271
     272
     273                        //ネイティブコードバッファの再確保
     274                        extern int obp_AllocSize;
     275                        if(obp_AllocSize<obp+8192){
     276                            obp_AllocSize+=8192;
     277                            OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
     278                        }
     279                    }
     280                }
     281                else{
     282                    Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
     283                }
     284            }
     285        }
     286    }
     287
     288    if(indexSystemGC!=-1){
     289        //_System_GCオブジェクトのデストラクタの呼び出し処理
     290        i3=pVar[indexSystemGC].u.pobj_c->DestructorMemberSubIndex;
     291        if(i3!=-1){
     292            Opcode_CallProc("",pVar[indexSystemGC].u.pobj_c->ppobj_Method[i3]->psi,0,pVar[indexSystemGC].name,DEF_OBJECT);
     293        }
     294    }
     295}
     296
     297// Returnステートメントで発行されるデストラクタを生成
     298void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
     299    //現在のスコープレベルを退避
     300    int backupScopeLevel = GetNowLevel();
     301
     302    for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
     303        SetNowLevel( i );
     304
     305        CallDestructorsOfScopeEnd();
     306    }
     307
     308    //現在のスコープレベルを復元
     309    SetNowLevel( backupScopeLevel );
     310}
  • BasicCompiler_Common/LexicalScoping.h

    r4 r34  
    11
    22
     3enum SCOPE_TYPE{
     4    //ベース
     5    SCOPE_TYPE_BASE,
     6
     7    //分岐
     8    SCOPE_TYPE_IF,
     9
     10    //ループ
     11    SCOPE_TYPE_DO,
     12    SCOPE_TYPE_FOR,
     13    SCOPE_TYPE_WHILE,
     14
     15    //ケース分け
     16    SCOPE_TYPE_SELECT,
     17};
     18
     19class CScope{
     20    int level;
     21    int StartAddress;
     22    SCOPE_TYPE TypeOfStatement;
     23
     24    DWORD *pBreakSchedule;
     25    int nBreakSchedule;
     26
     27public:
     28    CScope( int level, int addr, SCOPE_TYPE TypeOfStatement );
     29    ~CScope();
     30
     31    int GetStartAddress();
     32    SCOPE_TYPE GetTypeOfStatement();
     33
     34    void Break();
     35    void RunScheduleOfBreak();
     36};
     37
    338class CLexicalScopes{
     39    CScope **ppScopes;
    440    int level;
    5     int StartAddresses[1024];
     41
     42    CScope *SearchScope( SCOPE_TYPE TypeOfStatement );
     43
    644public:
    745    CLexicalScopes();
    846    ~CLexicalScopes();
    947
     48    //初期化(関数コンパイルの開始時に呼び出される)
    1049    void Init(int addr);
    1150
    12     void LevelUp(int addr);
    13     void LevelDown(void);
     51    // スコープを開始
     52    void Start( int addr, SCOPE_TYPE TypeOfStatement );
     53
     54    //スコープを終了
     55    void End();
     56
     57    //スコープ抜け出しステートメント
     58    void Break();
     59    void ExitFor();
     60    void ExitWhile();
     61    void ExitDo();
    1462
    1563    int GetNowLevel(void);
     64    void SetNowLevel( int level );
    1665    int GetStartAddress(void);
     66
     67    //スコープ終了時のデストラクタ呼び出し
     68    void CallDestructorsOfScopeEnd();
     69
     70    //Returnステートメント用のデストラクタ呼び出し
     71    void CallDestructorsOfReturn( int BaseLevel = 0 );
    1772
    1873private:
  • BasicCompiler_Common/Object.cpp

    r31 r34  
    183183    }
    184184}
    185 
    186 
    187 void CallDestrouctorsOfScope(void){
    188     extern BOOL bCompilingGlobal;
    189     VARIABLE *pVar;
    190     int num;
    191     if(bCompilingGlobal){
    192         //グローバルオブジェクトの解放処理
    193         extern VARIABLE *GlobalVar;
    194         extern int MaxGlobalVarNum;
    195         pVar=GlobalVar;
    196         num=MaxGlobalVarNum;
    197     }
    198     else{
    199         //ローカルオブジェクトの解放処理
    200         extern VARIABLE *LocalVar;
    201         extern int MaxLocalVarNum;
    202         pVar=LocalVar;
    203         num=MaxLocalVarNum;
    204     }
    205 
    206 
    207     int i3,i4,i5;
    208     int indexSystemGC=-1;
    209     for(i3=0;i3<num;i3++){
    210 
    211         if(bCompilingGlobal&&obj_LexScopes.GetNowLevel()==0){
    212             if(lstrcmp(pVar[i3].name,"_System_GC")==0){
    213                 indexSystemGC=i3;
    214                 continue;
    215             }
    216         }
    217 
    218         //同一レベルのレキシカルスコープのみを検知
    219         if(!pVar[i3].bLiving) continue;
    220         if(pVar[i3].ScopeLevel!=obj_LexScopes.GetNowLevel()) continue;
    221 
    222         if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef&OBJECT_PARAMETER){
    223             //実態オブジェクトのパラメータを持つとき
    224 
    225             //デストラクタを呼び出す
    226             i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
    227             if(i5!=-1)
    228                 Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
    229 
    230             //メモリを解放する
    231 
    232 #ifdef _AMD64_
    233             //x64ビットコード
    234 
    235             //mov rcx,qword ptr[rsp+offset]
    236             op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
    237                 -pVar[i3].offset,
    238                 MOD_BASE_DISP32);
    239             obp-=sizeof(long);
    240             AddLocalVarAddrSchedule();
    241             obp+=sizeof(long);
    242 #else
    243             //x86コード
    244 
    245             //mov ecx,dword ptr[ebp+offset]
    246             op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32);
    247             obp-=sizeof(long);
    248             AddLocalVarAddrSchedule();
    249             obp+=sizeof(long);
    250 
    251             //push ecx
    252             op_push(REG_ECX);
    253 #endif
    254 
    255             //call free
    256             extern SUBINFO *pSub_free;
    257             op_call(pSub_free);
    258 
    259 
    260             if(bCompilingGlobal){
    261                 //ここには来ないハズ
    262                 SetError(300,NULL,cp);
    263             }
    264         }
    265         else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){
    266             //デストラクタの呼び出し
    267             i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
    268             if(i5!=-1){
    269                 int ss[MAX_ARRAYDIM];
    270                 memset(ss,0,MAX_ARRAYDIM*sizeof(int));
    271                 if(pVar[i3].SubScripts[0]!=-1){
    272                     while(1){
    273                         for(i4=0;;i4++){
    274                             if(pVar[i3].SubScripts[i4]==-1) break;
    275 
    276                             if(ss[i4]>pVar[i3].SubScripts[i4]){
    277                                 ss[i4]=0;
    278                                 ss[i4+1]++;
    279                             }
    280                             else break;
    281                         }
    282                         if(pVar[i3].SubScripts[i4]==-1) break;
    283                         char temporary[VN_SIZE];
    284                         sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]);
    285                         for(i4=1;;i4++){
    286                             if(pVar[i3].SubScripts[i4]==-1) break;
    287 
    288                             sprintf(temporary+lstrlen(temporary),",%d",ss[i4]);
    289                         }
    290                         lstrcat(temporary,"]");
    291                         Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,temporary,DEF_OBJECT);
    292 
    293                         ss[0]++;
    294 
    295 
    296                         //ネイティブコードバッファの再確保
    297                         extern int obp_AllocSize;
    298                         if(obp_AllocSize<obp+8192){
    299                             obp_AllocSize+=8192;
    300                             OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
    301                         }
    302                     }
    303                 }
    304                 else{
    305                     Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
    306                 }
    307             }
    308         }
    309     }
    310 
    311     if(indexSystemGC!=-1){
    312         //_System_GCオブジェクトのデストラクタの呼び出し処理
    313         i3=pVar[indexSystemGC].u.pobj_c->DestructorMemberSubIndex;
    314         if(i3!=-1){
    315             Opcode_CallProc("",pVar[indexSystemGC].u.pobj_c->ppobj_Method[i3]->psi,0,pVar[indexSystemGC].name,DEF_OBJECT);
    316         }
    317     }
    318 }
    319 
  • BasicCompiler_Common/PESchedule.cpp

    r5 r34  
    265265}
    266266void CTempSchedule::unlock(){
     267    if( num <= 0 ){
     268        //エラー
     269        SetError(300,NULL,cp);
     270    }
    267271    num--;
    268272}
  • BasicCompiler_Common/Variable.cpp

    r29 r34  
    648648
    649649        for(i=MaxLocalVarNum-1;i>=0;i--){   //レキシカルスコープを考慮してバックサーチ
    650             if(LocalVar[i].bLiving){
    651                 if(lstrcmp(VarName,LocalVar[i].name)==0) break;
     650            if( LocalVar[i].bLiving                                         //現在のスコープで有効なもの
     651                && LocalVar[i].ScopeLevel <= obj_LexScopes.GetNowLevel()    //現在のスコープレベルを超さないもの(Returnによる解放処理中を考慮)
     652                ){
     653                    if(lstrcmp(VarName,LocalVar[i].name)==0) break;
    652654            }
    653655        }
     
    766768
    767769    for(i=MaxGlobalVarNum-1;i>=0;i--){  //レキシカルスコープを考慮してバックサーチ
    768         if(GlobalVar[i].bLiving){
    769             if(lstrcmp(VarName,GlobalVar[i].name)==0) break;
     770        if( GlobalVar[i].bLiving                                        //現在のスコープで有効なもの
     771            && GlobalVar[i].ScopeLevel <= obj_LexScopes.GetNowLevel()   //現在のスコープレベルを超さないもの(Returnによる解放処理中を考慮)
     772            ){
     773                if(lstrcmp(VarName,GlobalVar[i].name)==0) break;
    770774        }
    771775    }
  • BasicCompiler_Common/common.h

    r31 r34  
    385385
    386386
    387 #include "../BasicCompiler_Common/schedule.h"
     387#include "../BasicCompiler_Common/PESchedule.h"
    388388#include "../BasicCompiler_Common/DebugSection.h"
    389389#include "../BasicCompiler_Common/LexicalScoping.h"
     
    423423void AddClassName(char *Parameter,int NowLine);
    424424void CallConstractor(char *VarName,int *SubScripts,TYPEINFO &TypeInfo,char *Parameter);
    425 void CallDestrouctorsOfScope(void);
    426425
    427426//Overload.sbp
  • BasicCompiler_Common/error.cpp

    r28 r34  
    143143    if(num==60) lstrcpy(msg,"Staticステートメントはグローバル領域では使用できません。");
    144144    if(num==61) sprintf(msg,"\"%s\" は定数です。書き込みアクセスはできません。",KeyWord);
     145    if(num==62) sprintf(msg,"グローバル領域でのReturnは禁止されています。",KeyWord);
    145146
    146147
Note: See TracChangeset for help on using the changeset viewer.