source: dev/trunk/abdev/BasicCompiler_Common/src/LexicalScopingImpl.cpp@ 245

Last change on this file since 245 was 234, checked in by dai_9181, 17 years ago
File size: 3.7 KB
Line 
1#include "stdafx.h"
2
3#include <LexicalScopingImpl.h>
4#include <Compiler.h>
5
6#include "../common.h"
7
8#ifdef _AMD64_
9#include "../../BasicCompiler64/opcode.h"
10#else
11#include "../../BasicCompiler32/opcode.h"
12#endif
13
14
15void ScopeImpl::Break(){
16 //未解放のローカルオブジェクトを解放する
17 GetLexicalScopes().CallDestructorsOfReturn( level );
18
19 //jmp ...(Next addr)
20 OpBuffer[obp++]=(char)0xE9;
21
22 pBreakSchedule=(DWORD *)realloc( pBreakSchedule, ( nBreakSchedule + 1 ) * sizeof(DWORD) );
23 pBreakSchedule[nBreakSchedule]=obp;
24 nBreakSchedule++;
25
26 obp+=sizeof(long);
27}
28void ScopeImpl::RunScheduleOfBreak(){
29 for(int i=0;i<nBreakSchedule;i++){
30 *((long *)(OpBuffer+pBreakSchedule[i]))=obp-(pBreakSchedule[i]+sizeof(long));
31 }
32}
33
34void LexicalScopesImpl::End(){
35 if( level <= 0 ){
36 SetError();
37 return;
38 }
39
40 //デストラクタを呼ぶ
41 CallDestructorsOfScopeEnd();
42
43 Variables &vars = UserProc::IsGlobalAreaCompiling() ?
44 compiler.GetMeta().GetGlobalVars() :
45 UserProc::CompilingUserProc().GetLocalVars();
46
47 //使用済みローカル変数の生存チェックを外す
48 BOOST_FOREACH( Variable *pVar, vars ){
49 if(pVar->bLiving&&pVar->GetScopeLevel()==level){
50 pVar->bLiving=0;
51 extern int obp;
52 pVar->SetScopeEndAddress( obp );
53 }
54 }
55
56
57 //スコープ抜け出しスケジュール
58 ppScopes[level]->RunScheduleOfBreak();
59
60
61 //スコープレベルを下げる
62 delete ppScopes[level];
63 level--;
64}
65
66// スコープ終了時のデストラクタ呼び出し
67void LexicalScopesImpl::CallDestructorsOfScopeEnd(){
68
69 Variables &vars = UserProc::IsGlobalAreaCompiling() ?
70 compiler.GetMeta().GetGlobalVars() :
71 UserProc::CompilingUserProc().GetLocalVars();
72
73
74 int i3;
75 int indexSystemGC=-1;
76 for( i3 = (int)vars.size() - 1; i3 >= 0; i3-- ){ //確保したのと逆順序で解放するため、バックサーチにする
77
78 Variable *pVar = vars[i3];
79
80 if( UserProc::IsGlobalAreaCompiling() && GetNowLevel() == 0 ){
81 if( pVar->GetName() == "_System_GC" ){
82 indexSystemGC=i3;
83 continue;
84 }
85 }
86
87 //同一レベルのレキシカルスコープのみを検知
88 if(!pVar->bLiving) continue;
89 if( pVar->GetScopeLevel() != GetNowLevel() ) continue;
90
91 if( pVar->GetType().IsStruct() && pVar->IsParameter() ){
92 //構造体パラメータを持つとき
93
94 //メモリを解放する
95
96#ifdef _AMD64_
97 //x64ビットコード
98
99 //mov rcx,qword ptr[rsp+offset]
100 compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
101 -pVar->GetOffsetAddress(),
102 MOD_BASE_DISP32,
103 Schedule::LocalVar);
104#else
105 //x86コード
106
107 //mov ecx,dword ptr[ebp+offset]
108 compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar->GetOffsetAddress(),MOD_BASE_DISP32, Schedule::LocalVar );
109
110 //push ecx
111 compiler.codeGenerator.op_push(REG_ECX);
112#endif
113
114 //call free
115 extern const UserProc *pSub_free;
116 compiler.codeGenerator.op_call(pSub_free);
117
118
119 if( UserProc::IsGlobalAreaCompiling() ){
120 //ここには来ないハズ
121 SetError(300,NULL,cp);
122 }
123 }
124 }
125
126 if(indexSystemGC!=-1){
127 //_System_GCオブジェクトのデストラクタの呼び出し処理
128 const CMethod *method = vars[indexSystemGC]->GetType().GetClass().GetDestructorMethod();
129 if( method ){
130 Opcode_CallProc("",&method->GetUserProc(),0,vars[indexSystemGC]->GetName().c_str(),DEF_OBJECT);
131 }
132 }
133}
134
135// Returnステートメントで発行されるデストラクタを生成
136void LexicalScopesImpl::CallDestructorsOfReturn( int BaseLevel ){
137 //現在のスコープレベルを退避
138 int backupScopeLevel = GetNowLevel();
139
140 for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
141 SetNowLevel( i );
142
143 CallDestructorsOfScopeEnd();
144 }
145
146 //現在のスコープレベルを復元
147 SetNowLevel( backupScopeLevel );
148}
149
150LexicalScopesImpl &GetLexicalScopes()
151{
152 static LexicalScopesImpl *pTemp = NULL;
153 if( !pTemp )
154 {
155 pTemp = (LexicalScopesImpl *)Smoothie::Temp::pLexicalScopes;
156 }
157 return *pTemp;
158}
Note: See TracBrowser for help on using the repository browser.