source: dev/trunk/abdev/BasicCompiler_Common/include/CodeGenerator.h@ 250

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

Selectステートメントのスケジュール機構をリファクタリング

File size: 16.5 KB
Line 
1#pragma once
2
3#include <NativeCode.h>
4#include <LexicalScope.h>
5
6#ifdef _AMD64_
7#include "../../BasicCompiler64/MachineFixed.h"
8#else
9#include "../../BasicCompiler32/MachineFixed.h"
10#endif
11
12void ReallocNativeCodeBuffer();
13
14//Goto未知ラベル
15class GotoLabelSchedule
16{
17 std::string name;
18 int line;
19 int nativeCodePos;
20 int sourceCodePos;
21public:
22 GotoLabelSchedule( const std::string &name, int nativeCodePos, int sourceCodePos )
23 : name( name )
24 , line( -1 )
25 , nativeCodePos( nativeCodePos )
26 , sourceCodePos( sourceCodePos )
27 {
28 }
29 GotoLabelSchedule( int line, int nativeCodePos, int sourceCodePos )
30 : line( line )
31 , nativeCodePos( nativeCodePos )
32 , sourceCodePos( sourceCodePos )
33 {
34 }
35 const std::string &GetName() const
36 {
37 return name;
38 }
39 int GetLineNum() const
40 {
41 return line;
42 }
43 int GetNativeCodePos() const
44 {
45 return nativeCodePos;
46 }
47 int GetSourceCodePos() const
48 {
49 return sourceCodePos;
50 }
51};
52
53// コード生成時の部分的なスケジューリング
54class PertialSchedule
55{
56 int codePos; // バッファ位置
57 int typeSize; // 対象サイズ(一般的には8bit/32bit)
58
59 int _obpOld; // 未完成
60public:
61 PertialSchedule( int codePos, int typeSize )
62 : codePos( codePos )
63 , typeSize( typeSize )
64 {
65 extern int obp;
66 _obpOld = obp;
67 }
68 ~PertialSchedule()
69 {
70 }
71
72 int GetCodePos() const
73 {
74 return codePos;
75 }
76 int GetTypeSize() const
77 {
78 return typeSize;
79 }
80 int GetObpOld() const
81 {
82 return _obpOld;
83 }
84};
85typedef std::vector<const PertialSchedule *> PertialSchedules;
86
87class LexicalScope
88{
89public:
90 enum SCOPE_TYPE{
91 //ベース
92 SCOPE_TYPE_BASE,
93
94 //分岐
95 SCOPE_TYPE_IF,
96
97 //ループ
98 SCOPE_TYPE_DO,
99 SCOPE_TYPE_FOR,
100 SCOPE_TYPE_WHILE,
101
102 //ケース分け
103 SCOPE_TYPE_SELECT,
104 };
105
106private:
107 int level;
108 int StartAddress;
109 SCOPE_TYPE TypeOfStatement;
110
111 PertialSchedules breakPertialSchedules;
112
113public:
114 LexicalScope( int level, int addr, SCOPE_TYPE TypeOfStatement )
115 : level( level )
116 , StartAddress( addr )
117 , TypeOfStatement( TypeOfStatement )
118 {
119 }
120 ~LexicalScope()
121 {
122 }
123
124 int GetStartAddress()
125 {
126 return StartAddress;
127 }
128 SCOPE_TYPE GetTypeOfStatement()
129 {
130 return TypeOfStatement;
131 }
132
133 void Break();
134 void RunScheduleOfBreak();
135};
136
137class LexicalScopes
138{
139 LexicalScope **ppScopes;
140 int level;
141
142public:
143
144 LexicalScopes(){
145 ppScopes = (LexicalScope **)malloc( 1 );
146 level=0;
147 }
148 ~LexicalScopes(){
149 free( ppScopes );
150 }
151
152 //初期化(関数コンパイルの開始時に呼び出される)
153 void Init(int addr);
154
155 // スコープを開始
156 void Start( int addr, LexicalScope::SCOPE_TYPE TypeOfStatement );
157
158 // スコープを検索
159 LexicalScope *SearchScope( LexicalScope::SCOPE_TYPE TypeOfStatement );
160
161 int GetNowLevel(void);
162 void SetNowLevel( int level );
163 int GetStartAddress(void);
164
165 void End();
166
167 //スコープ終了時のデストラクタ呼び出し
168 void CallDestructorsOfScopeEnd();
169
170 //Returnステートメント用のデストラクタ呼び出し
171 void CallDestructorsOfReturn( int BaseLevel = 0 );
172};
173
174class CodeGenerator
175{
176 NativeCode *pNativeCode;
177
178private:
179 // 部分スケジュールの管理
180 PertialSchedules pertialSchedules;
181
182 // Continue用のコード位置情報の管理
183 std::vector<long> continueCodePositions;
184 std::vector<long> _continueCodePositions_ObpOld;
185
186public:
187
188 // Exit Subスケジュールの管理
189 std::vector<long> exitSubCodePositions;
190 std::vector<int> _exitSubCodePositions_ObpOld;
191
192 // Gotoスケジュールの管理
193 std::vector<GotoLabelSchedule> gotoLabelSchedules;
194
195 // レキシカルスコープの管理
196 LexicalScopes lexicalScopes;
197
198 CodeGenerator()
199 : pNativeCode( 0 )
200 {
201 }
202 ~CodeGenerator()
203 {
204 if( pNativeCode )
205 {
206 CheckUnresolveSchedule();
207 }
208 }
209
210 void Select( NativeCode &nativeCode )
211 {
212 if( pNativeCode )
213 {
214 CheckUnresolveSchedule();
215 }
216 pNativeCode = &nativeCode;
217 }
218
219 long GetContinueCodePos() const
220 {
221 if( continueCodePositions.size() == 0 )
222 {
223 return -1;
224 }
225 return continueCodePositions[continueCodePositions.size()-1];
226 }
227 void ClearContinueArea()
228 {
229 continueCodePositions.clear();
230 _continueCodePositions_ObpOld.clear();
231 }
232 void ContinueAreaBegin()
233 {
234 continueCodePositions.push_back( pNativeCode->GetSize() );
235
236 extern int obp;
237 _continueCodePositions_ObpOld.push_back( obp );
238 }
239 void ContinueAreaEnd()
240 {
241 continueCodePositions.pop_back();
242 _continueCodePositions_ObpOld.pop_back();
243 }
244 long GetContinueCodePosOld() const
245 {
246 if( _continueCodePositions_ObpOld.size() == 0 )
247 {
248 return -1;
249 }
250 return _continueCodePositions_ObpOld[_continueCodePositions_ObpOld.size()-1];
251 }
252
253 void ResolveExitSubSchedule();
254
255 void CheckUnresolveSchedule();
256
257 void opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule );
258
259
260 /////////////////////////////////////////////////////////////////
261 // 32bit/64bit共通 機械語生成
262 /////////////////////////////////////////////////////////////////
263
264private:
265 const PertialSchedule *__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
266public:
267 const PertialSchedule *op_jle( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
268 const PertialSchedule *op_jbe( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
269 const PertialSchedule *op_jge( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
270 const PertialSchedule *op_jae( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
271 const PertialSchedule *op_jl( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
272 const PertialSchedule *op_jb( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
273 const PertialSchedule *op_jg( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
274 const PertialSchedule *op_ja( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
275 const PertialSchedule *op_jne( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
276 const PertialSchedule *op_je( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
277 const PertialSchedule *op_jmp( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false );
278 void op_jmp_continue();
279 void op_jmp_exitsub();
280 void op_jmp_goto_schedule( const GotoLabelSchedule &gotoLabelSchedule );
281
282
283#ifdef _AMD64_
284 /////////////////////////////////////////////////////////////////
285 // 64ビット機械語生成
286 /////////////////////////////////////////////////////////////////
287private:
288 void set_rex(int op_size,int reg,int index_reg,int base_reg);
289 void set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType = Schedule::None );
290 void __op_format(int op_size,char op_prefix,char opcode1,char opcode2,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None );
291public:
292 void op_mov_RV (int op_size,int reg,long i32data, Schedule::Type scheduleType = Schedule::None );
293 void op_mov_RV64 (int reg,_int64 i64data);
294 void op_mov_RM (int op_size,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None );
295 void op_mov_RM_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None );
296 void op_mov_MR (int op_size,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None );
297 void op_mov_MR_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None );
298 void op_mov_MV (int op_size,int base_reg,int offset, Schedule::Type offsetScheduleType, BOOL bUseOffset,long i32data);
299 void op_mov_RR (int reg1,int reg2);
300 void op_movsxd (int reg64,int reg32);
301 void op_movsx64_FromReg16 (int reg64,int reg16);
302 void op_movsx64_FromReg8 (int reg64,int reg8);
303 void op_movsx32_FromReg16 (int reg32,int reg16);
304 void op_movsx32_FromReg8 (int reg32,int reg8);
305 void op_movsx16_FromReg8 (int reg32,int reg8);
306 void op_cqo ();
307 void op_inc (int reg);
308 void op_dec (int reg);
309 void op_add_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
310 void op_add_RV (int reg,long offset, Schedule::Type scheduleType = Schedule::None );
311 void op_add_RR (int reg1,int reg2);
312 void op_add32_reg (int reg1,int reg2);
313 void op_sub_RV (int op_size,int reg,long i32data);
314 void op_sub64_reg (int reg1,int reg2);
315 void op_sub32_reg (int reg1,int reg2);
316 void op_sbb_RR ( int op_size, int reg1, int reg2 );
317 void op_imul_RR (int op_size,int reg1,int reg2);
318 void op_imul_RV (int op_size,int reg,long i32data);
319 void op_div64_reg (int reg);
320 void op_idiv64_reg (int reg);
321 void op_shl_reg (int op_size,int reg);
322 void op_sar_reg (int op_size,int reg);
323 void op_shr_reg (int op_size,int reg);
324 void op_and_reg (int op_size,int reg1,int reg2);
325 void op_and64_value (int reg,long offset);
326 void op_and32_value (int reg,long offset);
327 void op_or_reg (int op_size,int reg1,int reg2);
328 void op_xor_reg (int op_size,int reg1,int reg2);
329 void op_not_reg (int op_size,int reg);
330 void op_neg ( int reg );
331 void op_test (int reg1,int reg2);
332 void op_cmp_reg (int op_size,int reg1,int reg2);
333 void op_cmp_value (int op_size,int reg,char byte_data);
334 void op_setne (int reg);
335 void op_movlpd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
336 void op_movlpd_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
337 void op_movsd_RR (int xmm_reg1,int xmm_reg2);
338 void op_movsd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
339 void op_movss_RR (int xmm_reg1,int xmm_reg2);
340 void op_movss_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
341 void op_movss_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
342 void op_movd_RX (int reg,int xmm_reg);
343 void op_cvtsd2ss (int xmm_reg1,int xmm_reg2);
344 void op_cvtss2sd (int xmm_reg1,int xmm_reg2);
345 void op_cvttsd2si_xmm (int op_size,int reg,int xmm_reg);
346 void op_cvttss2si_xmm (int op_size,int reg,int xmm_reg);
347 void op_cvtsi2sd_reg (int op_size,int xmm_reg,int reg);
348 void op_cvtsi2ss_reg (int op_size,int xmm_reg,int reg);
349 void op_comisd (int xmm_reg1,int xmm_reg2);
350 void op_comiss (int xmm_reg1,int xmm_reg2);
351 void op_rep_movs (int op_size);
352 void op_add_rsp(long num);
353 void op_sub_rsp(long num);
354 void op_add_esp(long num);
355 void op_sub_esp(long num);
356 void op_fld_ptr_esp(int type);
357 void op_zero_reg(int reg);
358 void op_call( const UserProc *pUserProc );
359 void op_call( const DllProc *pDllProc );
360 void op_ret();
361
362#else
363 /////////////////////////////////////////////////////////////////
364 // 32ビット機械語生成
365 /////////////////////////////////////////////////////////////////
366private:
367 void set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType = Schedule::None );
368 void __op_format(char op_prefix,char opcode,int reg);
369 void __op_format(char op_prefix,char opcode1,char opcode2,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
370public:
371 void op_mov_MV ( int op_size, int base_reg, long offset, Schedule::Type offsetScheduleType, long value, Schedule::Type valueScheduleType = Schedule::None );
372 void op_mov_RV (int reg,long offset, Schedule::Type scheduleType = Schedule::None );
373 void op_mov_RR (int reg1,int reg2);
374 void op_mov_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
375 void op_mov_RM_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None );
376 void op_mov_MR (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
377 void op_mov_MR_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None );
378 void op_movsx_R32R16 (int reg32,int reg16 = REG_NON);
379 void op_movsx_R32R8 (int reg32,int reg8 = REG_NON);
380 void op_movsx_R16R8 (int reg16,int reg8 = REG_NON);
381 void op_lea_RM ( int reg, int base_reg, long offset, char mod, Schedule::Type scheduleType = Schedule::None );
382 void op_inc (int reg);
383 void op_dec (int reg);
384 void op_add_RV8 (int reg,char cValue);
385 void op_add_RV ( int reg, long offset, Schedule::Type scheduleType = Schedule::None );
386 void op_add_RR ( int reg1, int reg2 );
387 void op_add_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None );
388 void op_adc_RV8 (int reg,char cValue);
389 void op_adc_RR ( int reg1, int reg2 );
390 void op_sub_RV8 (int reg,char cValue);
391 void op_sub_RR ( int reg1, int reg2 );
392 void op_sbb_RV8 (int reg,char cValue);
393 void op_sbb_RR ( int reg1, int reg2 );
394 void op_imul_RR (int reg1,int reg2);
395 void op_imul_RV (int reg,long i32data);
396 void op_imul_RV8 (int reg,char cValue);
397 void op_div_R ( int reg );
398 void op_idiv_R ( int reg );
399 void op_and_RV (int reg,long value);
400 void op_and_RR ( int reg1, int reg2 );
401 void op_or_RR ( int op_size, int reg1, int reg2 );
402 void op_xor_RR ( int reg1, int reg2 = REG_NON );
403 void op_neg ( int reg );
404 void op_cdq ();
405
406 void op_rep_movs (int op_size);
407
408 void op_push(int reg);
409 void op_push_V( long data, Schedule::Type scheduleType = Schedule::None );
410 void op_push_M( int base_reg );
411 void op_push_M( int base_reg, long offset, Schedule::Type scheduleType = Schedule::None );
412 void op_pop(int reg = REG_NON);
413 void op_add_esp(long num);
414 void op_sub_esp(long num);
415 void op_cmp_RR( int reg1, int reg2 );
416 void op_cmp_value(int op_size,int reg,char byte_data);
417 void op_setne( int reg );
418 void op_test(int reg1,int reg2);
419 void op_test_ah( char cValue );
420 void op_fld_ptr_esp(int type);
421 void op_fld_basereg (int type,int base_reg);
422 void op_fld_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None );
423 void op_fld_base_offset_ex (int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None);
424 void op_fstp_basereg (int type,int base_reg);
425 void op_fstp_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None);
426 void op_fstp_base_offset_ex (int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None);
427 void op_fistp_ptr_esp ( int typeSize );
428 void op_fstp_push ( Type &type );
429 void op_fcompp();
430 void op_fnstsw_ax();
431 void op_zero_reg(int reg);
432 void fpu_cast();
433 void fpu_cast_end();
434
435 void op_call_R( int reg );
436 void op_call(const UserProc *pUserProc);
437 void op_call(const DllProc *pDllProc);
438 void op_ret();
439 void op_ret( short stackFrameSize );
440 void op_addressof( int reg, const UserProc *pUserProc );
441#endif
442
443
444
445 void PutOld( long l, Schedule::Type scheduleType )
446 {
447 pNativeCode->Put( l, scheduleType );
448 }
449
450 void PutOld( char c1, char c2 )
451 {
452 pNativeCode->Put( c1 );
453 pNativeCode->Put( c2 );
454 }
455 void PutOld( char c1, char c2, char c3 )
456 {
457 pNativeCode->Put( c1 );
458 pNativeCode->Put( c2 );
459 pNativeCode->Put( c3 );
460 }
461 void PutOld( char c1, char c2, char c3, char c4 )
462 {
463 pNativeCode->Put( c1 );
464 pNativeCode->Put( c2 );
465 pNativeCode->Put( c3 );
466 pNativeCode->Put( c4 );
467 }
468 void PutOld( char c1, char c2, char c3, long l )
469 {
470 pNativeCode->Put( c1 );
471 pNativeCode->Put( c2 );
472 pNativeCode->Put( c3 );
473 pNativeCode->Put( l );
474 }
475 void PutOld( char c1, char c2, char c3, char c4, char c5 )
476 {
477 pNativeCode->Put( c1 );
478 pNativeCode->Put( c2 );
479 pNativeCode->Put( c3 );
480 pNativeCode->Put( c4 );
481 pNativeCode->Put( c5 );
482 }
483 void PutOld( char c1, char c2, char c3, char c4, char c5, char c6 )
484 {
485 pNativeCode->Put( c1 );
486 pNativeCode->Put( c2 );
487 pNativeCode->Put( c3 );
488 pNativeCode->Put( c4 );
489 pNativeCode->Put( c5 );
490 pNativeCode->Put( c6 );
491 }
492};
Note: See TracBrowser for help on using the repository browser.