#pragma once #include #ifdef _AMD64_ #include "../../compiler_x64/MachineFixed.h" #else #include "../../compiler_x86/MachineFixed.h" #endif // コード生成時の部分的なスケジューリング class PertialSchedule { int codePos; // バッファ位置 int typeSize; // 対象サイズ(一般的には8bit/32bit) public: PertialSchedule( int codePos, int typeSize ) : codePos( codePos ) , typeSize( typeSize ) { } ~PertialSchedule() { } int GetCodePos() const { return codePos; } int GetTypeSize() const { return typeSize; } }; typedef std::vector PertialSchedules; //Goto未知ラベル class GotoLabelSchedule : public PertialSchedule { std::string name; int line; int sourceCodePos; public: GotoLabelSchedule( const std::string &name, int nativeCodePos, int sourceCodePos ) : PertialSchedule( nativeCodePos, sizeof(long) ) , name( name ) , line( -1 ) , sourceCodePos( sourceCodePos ) { } GotoLabelSchedule( int line, int nativeCodePos, int sourceCodePos ) : PertialSchedule( nativeCodePos, sizeof(long) ) , line( line ) , sourceCodePos( sourceCodePos ) { } const std::string &GetName() const { return name; } int GetLineNum() const { return line; } int GetSourceCodePos() const { return sourceCodePos; } }; typedef std::vector GotoLabelSchedules; //ラベルアドレス class GotoLabel { public: std::string name; int line; DWORD address; GotoLabel( const std::string &name, long nativeCodePos ) : name( name ) , line( -1 ) , address( nativeCodePos ) { } GotoLabel( int line, long nativeCodePos ) : name( "" ) , line( line ) , address( nativeCodePos ) { } }; typedef std::vector GotoLabels; class LexicalScope { public: enum SCOPE_TYPE{ // ベース SCOPE_TYPE_BASE, // 分岐 SCOPE_TYPE_IF, // ループ SCOPE_TYPE_DO, SCOPE_TYPE_FOR, SCOPE_TYPE_WHILE, // ケース分け SCOPE_TYPE_SELECT, // 例外処理 SCOPE_TRY, SCOPE_CATCH, SCOPE_FINALLY, }; private: int level; int StartAddress; SCOPE_TYPE TypeOfStatement; PertialSchedules breakPertialSchedules; public: LexicalScope( int level, int addr, SCOPE_TYPE TypeOfStatement ) : level( level ) , StartAddress( addr ) , TypeOfStatement( TypeOfStatement ) { } ~LexicalScope() { } int GetStartAddress() { return StartAddress; } SCOPE_TYPE GetTypeOfStatement() { return TypeOfStatement; } void Break(); void RunScheduleOfBreak(); }; class LexicalScopes { LexicalScope **ppScopes; int level; public: LexicalScopes(){ ppScopes = (LexicalScope **)malloc( 1 ); level=0; } ~LexicalScopes(){ free( ppScopes ); } //初期化(関数コンパイルの開始時に呼び出される) void Init(int addr); // スコープを開始 void Start( int addr, LexicalScope::SCOPE_TYPE TypeOfStatement ); // スコープを検索 LexicalScope *SearchScope( LexicalScope::SCOPE_TYPE TypeOfStatement ); int GetNowLevel(void); void SetNowLevel( int level ); int GetStartAddress(void); void End(); //スコープ終了時のデストラクタ呼び出し void CallDestructorsOfScopeEnd(); //Returnステートメント用のデストラクタ呼び出し void CallDestructorsOfReturn( int BaseLevel = 0 ); }; class CodeGenerator { NativeCode *pNativeCode; private: // 部分スケジュールの管理 PertialSchedules pertialSchedules; // Continue用のコード位置情報の管理 std::vector continueCodePositions; // コンパイル中のステップにおいて、構造体の一時オブジェクトの解放が必要かどうか bool isNeedFreeTempStructureInCurrentStep; public: // ローカル変数用スケジュールの管理 PertialSchedules localVarPertialSchedules; // Exit Subスケジュールの管理 std::vector exitSubCodePositions; // Gotoスケジュールの管理 GotoLabels gotoLabels; GotoLabelSchedules gotoLabelSchedules; // レキシカルスコープの管理 LexicalScopes lexicalScopes; CodeGenerator() : pNativeCode( 0 ) , isNeedFreeTempStructureInCurrentStep( false ) { } ~CodeGenerator() { if( pNativeCode ) { CheckUnresolveSchedule(); } } void Select( NativeCode &nativeCode ) { if( pNativeCode ) { CheckUnresolveSchedule(); } pNativeCode = &nativeCode; } long GetNativeCodeSize() const { return pNativeCode->GetSize(); } void NextSourceLine( int currentSourceIndex ) { extern int cp; pNativeCode->NextSourceLine( currentSourceIndex, cp ); } long GetContinueCodePos() const { if( continueCodePositions.size() == 0 ) { return -1; } return continueCodePositions[continueCodePositions.size()-1]; } void ClearContinueArea() { continueCodePositions.clear(); } void ContinueAreaBegin() { continueCodePositions.push_back( pNativeCode->GetSize() ); } void ContinueAreaEnd() { continueCodePositions.pop_back(); } void PutWithSchedule( long l, Schedule::Type scheduleType ); void ResolveExitSubSchedule(); void CheckUnresolveSchedule(); void opfix( const PertialSchedule *pPertialSchedule, _int64 newValue ); void opfix_offset( const PertialSchedule *pPertialSchedule, long offset ); void opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule ); ///////////////////////////////////////////////////////////////// // 32bit/64bit共通 機械語生成 ///////////////////////////////////////////////////////////////// private: const PertialSchedule *__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); public: const PertialSchedule *op_jle( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jbe( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jge( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jae( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jl( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jb( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jg( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_ja( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jne( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_je( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); const PertialSchedule *op_jmp( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); void op_jmp_continue(); void op_jmp_exitsub(); void op_jmp_goto_schedule( const std::string &name, int lineNum, int sourceCodePos ); void op_AddNeedFreeTempStructure( int reg ); void op_FreeTempStructure(); #ifdef _AMD64_ ///////////////////////////////////////////////////////////////// // 64ビット機械語生成 ///////////////////////////////////////////////////////////////// private: void set_rex(int op_size,int reg,int index_reg,int base_reg); 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 ); 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 ); public: const PertialSchedule *op_mov_RV (int op_size,int reg,long i32data, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); const PertialSchedule *op_mov_RV64 ( int reg, _int64 i64data, bool isPertialSchedule = false ); 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 ); 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 ); 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 ); 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 ); const PertialSchedule *op_mov_MV (int op_size,int base_reg,int offset, Schedule::Type offsetScheduleType, bool isPertialSchedule, BOOL bUseOffset,long i32data); void op_mov_RR (int reg1,int reg2); void op_movsxd (int reg64,int reg32); void op_movsx64_FromReg16 (int reg64,int reg16); void op_movsx64_FromReg8 (int reg64,int reg8); void op_movsx32_FromReg16 (int reg32,int reg16); void op_movsx32_FromReg8 (int reg32,int reg8); void op_movsx16_FromReg8 (int reg32,int reg8); void op_cqo (); void op_inc (int reg); void op_dec (int reg); 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 ); const PertialSchedule *op_add_RV (int reg,long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_add_RR (int reg1,int reg2); void op_add32_reg (int reg1,int reg2); void op_sub_RV (int op_size,int reg,long i32data); void op_sub64_reg (int reg1,int reg2); void op_sub32_reg (int reg1,int reg2); void op_sbb_RR ( int op_size, int reg1, int reg2 ); void op_imul_RR (int op_size,int reg1,int reg2); void op_imul_RV (int op_size,int reg,long i32data); void op_div64_reg (int reg); void op_idiv64_reg (int reg); void op_shl_reg (int op_size,int reg); void op_sar_reg (int op_size,int reg); void op_shr_reg (int op_size,int reg); void op_and_reg (int op_size,int reg1,int reg2); void op_and64_value (int reg,long offset); void op_and32_value (int reg,long offset); void op_or_reg (int op_size,int reg1,int reg2); void op_xor_reg (int op_size,int reg1,int reg2); void op_not_reg (int op_size,int reg); void op_neg ( int reg ); void op_test (int reg1,int reg2); void op_cmp_reg (int op_size,int reg1,int reg2); void op_cmp_value (int op_size,int reg,char byte_data); void op_setne (int reg); const PertialSchedule *op_movlpd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); const PertialSchedule *op_movlpd_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_movsd_RR (int xmm_reg1,int xmm_reg2); const PertialSchedule *op_movsd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_movss_RR (int xmm_reg1,int xmm_reg2); const PertialSchedule *op_movss_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); const PertialSchedule *op_movss_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_movd_RX (int reg,int xmm_reg); void op_cvtsd2ss (int xmm_reg1,int xmm_reg2); void op_cvtss2sd (int xmm_reg1,int xmm_reg2); void op_cvttsd2si_xmm (int op_size,int reg,int xmm_reg); void op_cvttss2si_xmm (int op_size,int reg,int xmm_reg); void op_cvtsi2sd_reg (int op_size,int xmm_reg,int reg); void op_cvtsi2ss_reg (int op_size,int xmm_reg,int reg); void op_comisd (int xmm_reg1,int xmm_reg2); void op_comiss (int xmm_reg1,int xmm_reg2); void op_rep_movs (int op_size); void op_add_rsp(long num); const PertialSchedule *op_sub_rsp( long num, bool isPertialSchedule = false ); void op_fld_ptr_esp(int type); void op_zero_reg(int reg); void op_call( const UserProc *pUserProc ); void op_call( const DllProc *pDllProc ); void op_ret(); void op_addressof( int reg, const UserProc *pUserProc ); void op_mov_RV_com_vtbl( int reg, const CClass *pClass ); void op_mov_RV_vtbl( int reg, const CClass *pClass ); #else ///////////////////////////////////////////////////////////////// // 32ビット機械語生成 ///////////////////////////////////////////////////////////////// private: 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 ); void __op_format(char op_prefix,char opcode,int reg); 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 ); public: 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 ); const PertialSchedule *op_mov_RV ( int reg, long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_mov_RR ( int reg1,int reg2); 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 ); 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 ); 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 ); 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 ); void op_movsx_R32R16 ( int reg32,int reg16 = REG_NON); void op_movsx_R32R8 ( int reg32,int reg8 = REG_NON); void op_movsx_R16R8 ( int reg16,int reg8 = REG_NON); const PertialSchedule *op_lea_RM ( int reg, int base_reg, long offset, char mod, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_inc (int reg); void op_dec (int reg); void op_add_RV8 (int reg,char cValue); const PertialSchedule *op_add_RV ( int reg, long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_add_RR ( int reg1, int reg2 ); 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 ); void op_adc_RV8 (int reg,char cValue); void op_adc_RR ( int reg1, int reg2 ); void op_sub_RV8 (int reg,char cValue); void op_sub_RR ( int reg1, int reg2 ); void op_sbb_RV8 (int reg,char cValue); void op_sbb_RR ( int reg1, int reg2 ); void op_imul_RR (int reg1,int reg2); void op_imul_RV (int reg,long i32data); void op_imul_RV8 (int reg,char cValue); void op_div_R ( int reg ); void op_idiv_R ( int reg ); void op_and_RV (int reg,long value); void op_and_RR ( int reg1, int reg2 ); void op_or_RR ( int op_size, int reg1, int reg2 ); void op_xor_RR ( int reg1, int reg2 = REG_NON ); void op_neg ( int reg ); void op_cdq (); void op_rep_movs (int op_size); void op_push(int reg); void op_push_V( long data, Schedule::Type scheduleType = Schedule::None ); void op_push_M( int base_reg ); const PertialSchedule *op_push_M( int base_reg, long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); void op_pop(int reg = REG_NON); void op_add_esp(long num); const PertialSchedule *op_sub_esp( long num, bool isPertialSchedule = false ); void op_cmp_RR( int reg1, int reg2 ); void op_cmp_value(int op_size,int reg,char byte_data); void op_setne( int reg ); void op_test(int reg1,int reg2); void op_test_ah( char cValue ); void op_fld_ptr_esp(int type); void op_fld_basereg (int type,int base_reg); const PertialSchedule *op_fld_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); 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 ); void op_fstp_basereg (int type,int base_reg); const PertialSchedule *op_fstp_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None, bool isPertialSchedule = false ); 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 ); void op_fistp_ptr_esp ( int typeSize ); void op_fstp_push ( Type &type ); void op_fcompp(); void op_fnstsw_ax(); void op_zero_reg(int reg); void fpu_cast(); void fpu_cast_end(); void op_call_R( int reg ); void op_call(const UserProc *pUserProc); void op_call(const DllProc *pDllProc); void op_ret(); void op_ret( short stackFrameSize ); void op_addressof( int reg, const UserProc *pUserProc ); void op_mov_RV_com_vtbl( int reg, const CClass *pClass ); void op_mov_RV_vtbl( int reg, const CClass *pClass ); #endif void PutOld( long l, Schedule::Type scheduleType ) { this->PutWithSchedule( l, scheduleType ); } const PertialSchedule *PutOld( long l, bool isPertialSchedule ) { const PertialSchedule *pPertialSchedule; if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } pNativeCode->Put( l ); return pPertialSchedule; } void PutOld( const NativeCode &nativeCode ) { pNativeCode->PutEx( nativeCode ); } void PutOld( char c ) { pNativeCode->Put( c ); } void PutOld( char c1, char c2 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); } void PutOld( char c1, char c2, char c3 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); } void PutOld( char c1, char c2, char c3, char c4 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); } void PutOld( char c1, char c2, char c3, long l ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( l ); } void PutOld( char c1, char c2, char c3, char c4, char c5 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); pNativeCode->Put( c5 ); } void PutOld( char c1, char c2, char c3, char c4, char c5, char c6 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); pNativeCode->Put( c5 ); pNativeCode->Put( c6 ); } };