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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.