source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/LexicalScope.cpp @ 537

Last change on this file since 537 was 537, checked in by dai_9181, 15 years ago

UserProcクラスによるコンパイル中関数管理用メソッドを除去(すべてCompilerクラス内で処理するようにした)。

File size: 4.6 KB
Line 
1#include "stdafx.h"
2
3#include <LexicalScope.h>
4#include <Compiler.h>
5
6#include "../common.h"
7
8#ifdef _AMD64_
9#include "../../compiler_x64/opcode.h"
10#else
11#include "../../compiler_x86/opcode.h"
12#endif
13
14
15void LexicalScope::Break(){
16    //未解放のローカルオブジェクトを解放する
17    compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn( level );
18
19    //jmp ...(Next addr)
20    breakPertialSchedules.push_back(
21        compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
22    );
23}
24void LexicalScope::RunScheduleOfBreak(){
25    BOOST_FOREACH( const PertialSchedule *pBreakPertialSchedule, breakPertialSchedules )
26    {
27        compiler.codeGenerator.opfix_JmpPertialSchedule( pBreakPertialSchedule );
28    }
29}
30
31
32
33LexicalScope *LexicalScopes::SearchScope( LexicalScope::SCOPE_TYPE TypeOfStatement ){
34    for( int i = level; i>=0; i-- ){
35        if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){
36            return ppScopes[i];
37        }
38    }
39    return NULL;
40}
41
42void LexicalScopes::Init(int addr){
43    // TODO: エラーチェック
44
45    level = -1;
46    Start( addr, LexicalScope::SCOPE_TYPE_BASE );
47}
48void LexicalScopes::Start( int addr, LexicalScope::SCOPE_TYPE TypeOfStatement ){
49    level++;
50    ppScopes = (LexicalScope **)realloc( ppScopes, ( level + 1 ) * sizeof( LexicalScope * ) );
51    ppScopes[level] = new LexicalScope( level, addr, TypeOfStatement );
52}
53
54int LexicalScopes::GetNowLevel(){
55    return level;
56}
57void LexicalScopes::SetNowLevel( int level ){
58    this->level = level;
59}
60int LexicalScopes::GetStartAddress(){
61    return ppScopes[level]->GetStartAddress();
62}
63
64void LexicalScopes::End(){
65    if( level <= 0 ){
66        compiler.errorMessenger.OutputFatalError();
67        return;
68    }
69
70    //デストラクタを呼ぶ
71    CallDestructorsOfScopeEnd();
72
73    Variables *pVars = compiler.IsGlobalAreaCompiling() ?
74        &compiler.GetObjectModule().meta.GetGlobalVars() :
75        &compiler.GetCompilingUserProc().GetLocalVars();
76
77    //使用済みローカル変数の生存チェックを外す
78    BOOST_FOREACH( Variable *pVar, (*pVars) )
79    {
80        if( pVar->isLiving && pVar->GetScopeLevel() == level )
81        {
82            pVar->isLiving = false;
83            pVar->SetScopeEndAddress( compiler.codeGenerator.GetNativeCodeSize() );
84        }
85    }
86
87
88    //スコープ抜け出しスケジュール
89    ppScopes[level]->RunScheduleOfBreak();
90
91
92    //スコープレベルを下げる
93    delete ppScopes[level];
94    level--;
95}
96
97// スコープ終了時のデストラクタ呼び出し
98void LexicalScopes::CallDestructorsOfScopeEnd(){
99
100    Variables *pVariabls = compiler.IsGlobalAreaCompiling() ?
101        &compiler.GetObjectModule().meta.GetGlobalVars() :
102        &compiler.GetCompilingUserProc().GetLocalVars();
103
104
105    int i3;
106    int indexSystemGC=-1;
107    for( i3 = (int)pVariabls->size() - 1; i3 >= 0; i3-- ){      //確保したのと逆順序で解放するため、バックサーチにする
108
109        Variable *pVar = (*pVariabls)[i3];
110
111        if( compiler.IsGlobalAreaCompiling() && GetNowLevel() == 0 ){
112            if( pVar->GetName() == "_System_GC" ){
113                indexSystemGC=i3;
114                continue;
115            }
116        }
117
118        //同一レベルのレキシカルスコープのみを検知
119        if( !pVar->isLiving ) continue;
120        if( pVar->GetScopeLevel() != GetNowLevel() ) continue;
121
122        if( pVar->GetType().IsStruct() && pVar->IsParameter() ){
123            //構造体パラメータを持つとき
124
125            //メモリを解放する
126
127#ifdef _AMD64_
128            //x64ビットコード
129
130            //mov rcx,qword ptr[rsp+offset]
131            compiler.codeGenerator.localVarPertialSchedules.push_back(
132            compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
133                -pVar->GetOffsetAddress(),
134                MOD_BASE_DISP32,
135                Schedule::None, true)
136            );
137#else
138            //x86コード
139
140            //mov ecx,dword ptr[ebp+offset]
141            compiler.codeGenerator.localVarPertialSchedules.push_back(
142                compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->GetOffsetAddress(),MOD_BASE_DISP32, Schedule::None, true )
143            );
144
145            //push ecx
146            compiler.codeGenerator.op_push(REG_ECX);
147#endif
148
149            //call free
150            extern const UserProc *pSub_free;
151            compiler.codeGenerator.op_call(pSub_free);
152
153
154            if( compiler.IsGlobalAreaCompiling() ){
155                //ここには来ないハズ
156                compiler.errorMessenger.Output(300,NULL,cp);
157            }
158        }
159    }
160
161    if(indexSystemGC!=-1){
162        //_System_GCオブジェクトのデストラクタの呼び出し処理
163        const CMethod *method = (*pVariabls)[indexSystemGC]->GetType().GetClass().GetDestructorMethod();
164        if( method ){
165            Opcode_CallProc("",&method->GetUserProc(),0,(*pVariabls)[indexSystemGC]->GetName().c_str());
166        }
167    }
168}
169
170// Returnステートメントで発行されるデストラクタを生成
171void LexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
172    //現在のスコープレベルを退避
173    int backupScopeLevel = GetNowLevel();
174
175    for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
176        SetNowLevel( i );
177
178        CallDestructorsOfScopeEnd();
179    }
180
181    //現在のスコープレベルを復元
182    SetNowLevel( backupScopeLevel );
183}
Note: See TracBrowser for help on using the repository browser.