source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/CommonCodeGenerator.cpp@ 652

Last change on this file since 652 was 551, checked in by dai_9181, 17 years ago

・PutWithScheduleメソッドを追加。
・NativeCodeクラスが持つCompilerクラスへの依存度を除去した。

File size: 10.1 KB
Line 
1#include "stdafx.h"
2
3#include <CodeGenerator.h>
4
5#ifdef _AMD64_
6#include "../../compiler_x64/opcode.h"
7#else
8#include "../../compiler_x86/opcode.h"
9#endif
10
11
12void CodeGenerator::PutWithSchedule( long l, Schedule::Type scheduleType )
13{
14 if( scheduleType == Schedule::CatchAddress )
15 {
16 const UserProc *pCurrentUserProc = compiler.IsGlobalAreaCompiling()
17 ? UserProc::pGlobalProc
18 : &compiler.GetCompilingUserProc();
19
20 this->pNativeCode->PutCatchAddressSchedule( pCurrentUserProc, l );
21 }
22 else
23 {
24 this->pNativeCode->PutEx( l, scheduleType );
25 }
26}
27
28void CodeGenerator::ResolveExitSubSchedule()
29{
30 BOOST_FOREACH( long exitSubCodePosition, exitSubCodePositions )
31 {
32 pNativeCode->Overwrite( exitSubCodePosition, (long)( pNativeCode->GetSize()-(exitSubCodePosition+sizeof(long)) ) );
33 }
34}
35
36void CodeGenerator::CheckUnresolveSchedule()
37{
38 if( pertialSchedules.size() > 0 )
39 {
40 compiler.errorMessenger.OutputFatalError();
41 }
42}
43
44void CodeGenerator::opfix( const PertialSchedule *pPertialSchedule, _int64 newValue )
45{
46 bool isSuccessful = false;
47
48 PertialSchedules::iterator it = pertialSchedules.begin();
49 while( it != pertialSchedules.end() )
50 {
51 if( (*it) == pPertialSchedule )
52 {
53 if( pPertialSchedule->GetTypeSize() == sizeof(char) )
54 {
55 if( newValue < -128 || 127 < newValue )
56 {
57 // 範囲外
58 compiler.errorMessenger.OutputFatalError();
59 }
60
61 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue );
62 }
63 else if( pPertialSchedule->GetTypeSize() == sizeof(long) )
64 {
65 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), static_cast<long>(newValue) );
66 }
67 else if( pPertialSchedule->GetTypeSize() == sizeof(_int64) )
68 {
69 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue );
70 }
71 else
72 {
73 compiler.errorMessenger.OutputFatalError();
74 }
75
76 it = pertialSchedules.erase( it );
77 delete pPertialSchedule;
78
79 isSuccessful = true;
80 break;
81 }
82 else
83 {
84 it++;
85 }
86 }
87
88 if( isSuccessful == false )
89 {
90 compiler.errorMessenger.OutputFatalError();
91 }
92}
93
94void CodeGenerator::opfix_offset( const PertialSchedule *pPertialSchedule, long offset )
95{
96 bool isSuccessful = false;
97
98 PertialSchedules::iterator it = pertialSchedules.begin();
99 while( it != pertialSchedules.end() )
100 {
101 if( (*it) == pPertialSchedule )
102 {
103 if( pPertialSchedule->GetTypeSize() == sizeof(long) )
104 {
105 pNativeCode->Overwrite(
106 pPertialSchedule->GetCodePos(),
107 pNativeCode->GetLong(pPertialSchedule->GetCodePos()) + offset
108 );
109 }
110 else
111 {
112 compiler.errorMessenger.OutputFatalError();
113 }
114
115 it = pertialSchedules.erase( it );
116 delete pPertialSchedule;
117
118 isSuccessful = true;
119 break;
120 }
121 else
122 {
123 it++;
124 }
125 }
126
127 if( isSuccessful == false )
128 {
129 compiler.errorMessenger.OutputFatalError();
130 }
131}
132
133
134// 分岐関連
135void CodeGenerator::opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule )
136{
137 bool isSuccessful = false;
138
139 PertialSchedules::iterator it = pertialSchedules.begin();
140 while( it != pertialSchedules.end() )
141 {
142 if( (*it) == pPertialSchedule )
143 {
144 long newValue = pNativeCode->GetSize() - (pPertialSchedule->GetCodePos()+pPertialSchedule->GetTypeSize());
145
146 if( pPertialSchedule->GetTypeSize() == sizeof(char) )
147 {
148 if( newValue < -128 || 127 < newValue )
149 {
150 // 範囲外
151 compiler.errorMessenger.OutputFatalError();
152 }
153
154 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue );
155 }
156 else if( pPertialSchedule->GetTypeSize() == sizeof(long) )
157 {
158 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue );
159 }
160 else
161 {
162 compiler.errorMessenger.OutputFatalError();
163 }
164
165 it = pertialSchedules.erase( it );
166 delete pPertialSchedule;
167
168 isSuccessful = true;
169 }
170 else
171 {
172 it++;
173 }
174 }
175
176 if( isSuccessful == false )
177 {
178 compiler.errorMessenger.OutputFatalError();
179 }
180}
181const PertialSchedule *CodeGenerator::__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
182{
183 long beginCodePos = pNativeCode->GetSize();
184
185 if( opcode == (char)0xEB )
186 {
187 // jmp命令のとき
188 if( op_size == sizeof(char) )
189 {
190 pNativeCode->Put( (char)opcode );
191 }
192 else if( op_size == sizeof(long) )
193 {
194 pNativeCode->Put( (char)0xE9 );
195 }
196 else
197 {
198 compiler.errorMessenger.OutputFatalError();
199 }
200 }
201 else
202 {
203 if( op_size == sizeof(char) )
204 {
205 pNativeCode->Put( (char)((char)0x70 | opcode) );
206 }
207 else if( op_size == sizeof(long) )
208 {
209 pNativeCode->Put( (char)0x0F );
210 pNativeCode->Put( (char)((char)0x80 | opcode) );
211 }
212 else
213 {
214 compiler.errorMessenger.OutputFatalError();
215 }
216 }
217
218 const PertialSchedule *pPertialSchedule = NULL;
219 if( isPertialSchedule )
220 {
221 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), op_size ) );
222 pPertialSchedule = pertialSchedules.back();
223 }
224
225 if( isSelfOpcodeOffset )
226 {
227 // 自分自身の命令サイズを考慮する場合
228 offset -= ( pNativeCode->GetSize() - beginCodePos ) + op_size;
229 }
230
231 if( op_size == sizeof(char) )
232 {
233 pNativeCode->Put( (char)offset );
234 }
235 else if( op_size == sizeof(long) )
236 {
237 pNativeCode->Put( offset );
238 }
239 else
240 {
241 compiler.errorMessenger.OutputFatalError();
242 }
243
244 return pPertialSchedule;
245}
246const PertialSchedule *CodeGenerator::op_jle( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
247{
248 return __jmp_op_format( (char)0x0E, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
249}
250const PertialSchedule *CodeGenerator::op_jbe( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
251{
252 return __jmp_op_format( (char)0x06, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
253}
254const PertialSchedule *CodeGenerator::op_jge( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
255{
256 return __jmp_op_format( (char)0x0D, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
257}
258const PertialSchedule *CodeGenerator::op_jae( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
259{
260 return __jmp_op_format( (char)0x03, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
261}
262const PertialSchedule *CodeGenerator::op_jl( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
263{
264 return __jmp_op_format( (char)0x0C, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
265}
266const PertialSchedule *CodeGenerator::op_jb( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
267{
268 return __jmp_op_format( (char)0x02, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
269}
270const PertialSchedule *CodeGenerator::op_jg( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
271{
272 return __jmp_op_format( (char)0x0F, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
273}
274const PertialSchedule *CodeGenerator::op_ja( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
275{
276 return __jmp_op_format( (char)0x07, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
277}
278const PertialSchedule *CodeGenerator::op_jne( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
279{
280 return __jmp_op_format( (char)0x05, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
281}
282const PertialSchedule *CodeGenerator::op_je( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
283{
284 return __jmp_op_format( (char)0x04, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
285}
286const PertialSchedule *CodeGenerator::op_jmp( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
287{
288 return __jmp_op_format( (char)0xEB, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
289}
290void CodeGenerator::op_jmp_continue()
291{
292 if( GetContinueCodePos() == -1 )
293 {
294 compiler.errorMessenger.Output(12,"Continue",cp);
295 return;
296 }
297 op_jmp( GetContinueCodePos() - pNativeCode->GetSize(), sizeof(long), false, true );
298}
299void CodeGenerator::op_jmp_exitsub()
300{
301 // オペコード
302 pNativeCode->Put( (char)0xE9 );
303
304 exitSubCodePositions.push_back( pNativeCode->GetSize() );
305
306 pNativeCode->Put( (long)0 );
307}
308void CodeGenerator::op_jmp_goto_schedule( const std::string &name, int lineNum, int sourceCodePos )
309{
310 // オペコード
311 pNativeCode->Put( (char)0xE9 );
312
313 const GotoLabelSchedule *pGotoLabelSchedule = NULL;
314 if( name.size() == 0 )
315 {
316 pGotoLabelSchedule = new GotoLabelSchedule( name, pNativeCode->GetSize(), sourceCodePos );
317 }
318 else
319 {
320 pGotoLabelSchedule = new GotoLabelSchedule( name, pNativeCode->GetSize(), sourceCodePos );
321 }
322 gotoLabelSchedules.push_back( pGotoLabelSchedule );
323
324 pertialSchedules.push_back( pGotoLabelSchedule );
325
326 pNativeCode->Put( (long)0 );
327}
328
329void CodeGenerator::op_AddNeedFreeTempStructure( int reg )
330{
331#ifdef _AMD64_
332 //////////////////////////////////////////////////////
333 ///// レジスタ資源のバックアップ
334 { BACKUP_REGISTER_RESOURCE
335 //////////////////////////////////////////////////////
336
337 //mov rcx,reg
338 op_mov_RR( REG_RCX, reg );
339
340 //call _System_AddNeedFreeTempStructure
341 extern const UserProc *pSub_System_AddNeedFreeTempStructure;
342 op_call( pSub_System_AddNeedFreeTempStructure );
343
344 /////////////////////////////////////////////
345 ////// レジスタ資源を復元
346 RESTORE_REGISTER_RESOURCE
347 }////////////////////////////////////////////
348#else
349
350 //push useReg(引き続き利用するため、退避しておく)
351 compiler.codeGenerator.op_push( reg );
352
353 //push useReg
354 compiler.codeGenerator.op_push( reg );
355
356 //call _System_AddNeedFreeTempStructure
357 extern const UserProc *pSub_System_AddNeedFreeTempStructure;
358 compiler.codeGenerator.op_call( pSub_System_AddNeedFreeTempStructure );
359
360 //pop useReg(復元する)
361 compiler.codeGenerator.op_pop( reg );
362#endif
363
364 isNeedFreeTempStructureInCurrentStep = true;
365}
366void CodeGenerator::op_FreeTempStructure()
367{
368 if( !isNeedFreeTempStructureInCurrentStep )
369 {
370 // 解放の必要はない
371 return;
372 }
373
374 // call _System_FreeTempStructure
375 extern const UserProc *pSub_System_FreeTempStructure;
376 op_call( pSub_System_FreeTempStructure );
377
378 isNeedFreeTempStructureInCurrentStep = false;
379}
Note: See TracBrowser for help on using the repository browser.