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

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