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

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