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

Last change on this file since 648 was 551, checked in by dai_9181, 16 years ago

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

File size: 10.1 KB
RevLine 
[239]1#include "stdafx.h"
2
3#include <CodeGenerator.h>
4
[436]5#ifdef _AMD64_
[485]6#include "../../compiler_x64/opcode.h"
[436]7#else
[484]8#include "../../compiler_x86/opcode.h"
[436]9#endif
[239]10
[436]11
[551]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
[247]28void CodeGenerator::ResolveExitSubSchedule()
29{
30 BOOST_FOREACH( long exitSubCodePosition, exitSubCodePositions )
31 {
32 pNativeCode->Overwrite( exitSubCodePosition, (long)( pNativeCode->GetSize()-(exitSubCodePosition+sizeof(long)) ) );
33 }
34}
35
[239]36void CodeGenerator::CheckUnresolveSchedule()
37{
38 if( pertialSchedules.size() > 0 )
39 {
[465]40 compiler.errorMessenger.OutputFatalError();
[239]41 }
42}
43
[357]44void CodeGenerator::opfix( const PertialSchedule *pPertialSchedule, _int64 newValue )
[251]45{
46 bool isSuccessful = false;
[239]47
[251]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 // 範囲外
[465]58 compiler.errorMessenger.OutputFatalError();
[251]59 }
60
61 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue );
62 }
63 else if( pPertialSchedule->GetTypeSize() == sizeof(long) )
64 {
[357]65 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), static_cast<long>(newValue) );
66 }
67 else if( pPertialSchedule->GetTypeSize() == sizeof(_int64) )
68 {
[251]69 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue );
70 }
71 else
72 {
[465]73 compiler.errorMessenger.OutputFatalError();
[251]74 }
75
76 it = pertialSchedules.erase( it );
77 delete pPertialSchedule;
78
79 isSuccessful = true;
[253]80 break;
[251]81 }
82 else
83 {
84 it++;
85 }
86 }
87
88 if( isSuccessful == false )
89 {
[465]90 compiler.errorMessenger.OutputFatalError();
[251]91 }
92}
93
[253]94void CodeGenerator::opfix_offset( const PertialSchedule *pPertialSchedule, long offset )
95{
96 bool isSuccessful = false;
[251]97
[253]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 {
[465]112 compiler.errorMessenger.OutputFatalError();
[253]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 {
[465]129 compiler.errorMessenger.OutputFatalError();
[253]130 }
131}
132
133
[239]134// 分岐関連
135void CodeGenerator::opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule )
136{
137 bool isSuccessful = false;
138
[248]139 PertialSchedules::iterator it = pertialSchedules.begin();
[239]140 while( it != pertialSchedules.end() )
141 {
142 if( (*it) == pPertialSchedule )
143 {
[241]144 long newValue = pNativeCode->GetSize() - (pPertialSchedule->GetCodePos()+pPertialSchedule->GetTypeSize());
145
[239]146 if( pPertialSchedule->GetTypeSize() == sizeof(char) )
147 {
[241]148 if( newValue < -128 || 127 < newValue )
149 {
150 // 範囲外
[465]151 compiler.errorMessenger.OutputFatalError();
[241]152 }
[239]153
[241]154 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue );
[239]155 }
[241]156 else if( pPertialSchedule->GetTypeSize() == sizeof(long) )
157 {
158 pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue );
159 }
[239]160 else
161 {
[465]162 compiler.errorMessenger.OutputFatalError();
[239]163 }
164
[245]165 it = pertialSchedules.erase( it );
[239]166 delete pPertialSchedule;
167
168 isSuccessful = true;
169 }
170 else
171 {
172 it++;
173 }
174 }
175
176 if( isSuccessful == false )
177 {
[465]178 compiler.errorMessenger.OutputFatalError();
[239]179 }
180}
[248]181const PertialSchedule *CodeGenerator::__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]182{
[241]183 long beginCodePos = pNativeCode->GetSize();
[239]184
[241]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 {
[465]198 compiler.errorMessenger.OutputFatalError();
[241]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 {
[465]214 compiler.errorMessenger.OutputFatalError();
[241]215 }
216 }
217
[245]218 const PertialSchedule *pPertialSchedule = NULL;
[239]219 if( isPertialSchedule )
220 {
221 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), op_size ) );
[251]222 pPertialSchedule = pertialSchedules.back();
[239]223 }
224
[241]225 if( isSelfOpcodeOffset )
226 {
227 // 自分自身の命令サイズを考慮する場合
[276]228 offset -= ( pNativeCode->GetSize() - beginCodePos ) + op_size;
[241]229 }
230
[239]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 {
[465]241 compiler.errorMessenger.OutputFatalError();
[239]242 }
243
244 return pPertialSchedule;
245}
[250]246const PertialSchedule *CodeGenerator::op_jle( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]247{
[250]248 return __jmp_op_format( (char)0x0E, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]249}
[250]250const PertialSchedule *CodeGenerator::op_jbe( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]251{
[250]252 return __jmp_op_format( (char)0x06, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]253}
[250]254const PertialSchedule *CodeGenerator::op_jge( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]255{
[250]256 return __jmp_op_format( (char)0x0D, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]257}
[250]258const PertialSchedule *CodeGenerator::op_jae( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]259{
[250]260 return __jmp_op_format( (char)0x03, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]261}
[250]262const PertialSchedule *CodeGenerator::op_jl( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]263{
[250]264 return __jmp_op_format( (char)0x0C, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]265}
[250]266const PertialSchedule *CodeGenerator::op_jb( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]267{
[250]268 return __jmp_op_format( (char)0x02, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]269}
[250]270const PertialSchedule *CodeGenerator::op_jg( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]271{
[250]272 return __jmp_op_format( (char)0x0F, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]273}
[250]274const PertialSchedule *CodeGenerator::op_ja( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]275{
[250]276 return __jmp_op_format( (char)0x07, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]277}
[250]278const PertialSchedule *CodeGenerator::op_jne( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]279{
[250]280 return __jmp_op_format( (char)0x05, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]281}
[250]282const PertialSchedule *CodeGenerator::op_je( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]283{
[250]284 return __jmp_op_format( (char)0x04, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]285}
[248]286const PertialSchedule *CodeGenerator::op_jmp( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset )
[239]287{
[241]288 return __jmp_op_format( (char)0xEB, offset, op_size, isPertialSchedule, isSelfOpcodeOffset );
[239]289}
[241]290void CodeGenerator::op_jmp_continue()
291{
[254]292 if( GetContinueCodePos() == -1 )
[241]293 {
[465]294 compiler.errorMessenger.Output(12,"Continue",cp);
[241]295 return;
296 }
[254]297 op_jmp( GetContinueCodePos() - pNativeCode->GetSize(), sizeof(long), false, true );
[241]298}
[247]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}
[253]308void CodeGenerator::op_jmp_goto_schedule( const std::string &name, int lineNum, int sourceCodePos )
[246]309{
310 // オペコード
311 pNativeCode->Put( (char)0xE9 );
312
[253]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 );
[246]323
[253]324 pertialSchedules.push_back( pGotoLabelSchedule );
325
[246]326 pNativeCode->Put( (long)0 );
327}
[435]328
329void CodeGenerator::op_AddNeedFreeTempStructure( int reg )
330{
331#ifdef _AMD64_
332 //////////////////////////////////////////////////////
333 ///// レジスタ資源のバックアップ
334 { BACKUP_REGISTER_RESOURCE
335 //////////////////////////////////////////////////////
336
[436]337 //mov rcx,reg
338 op_mov_RR( REG_RCX, reg );
[435]339
[436]340 //call _System_AddNeedFreeTempStructure
341 extern const UserProc *pSub_System_AddNeedFreeTempStructure;
342 op_call( pSub_System_AddNeedFreeTempStructure );
[435]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.