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

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