#include "stdafx.h" #include #ifdef _AMD64_ #include "../../BasicCompiler64/opcode.h" #else #include "../../compiler_x86/opcode.h" #endif void CodeGenerator::ResolveExitSubSchedule() { BOOST_FOREACH( long exitSubCodePosition, exitSubCodePositions ) { pNativeCode->Overwrite( exitSubCodePosition, (long)( pNativeCode->GetSize()-(exitSubCodePosition+sizeof(long)) ) ); } } void CodeGenerator::CheckUnresolveSchedule() { if( pertialSchedules.size() > 0 ) { compiler.errorMessenger.OutputFatalError(); } } void CodeGenerator::opfix( const PertialSchedule *pPertialSchedule, _int64 newValue ) { bool isSuccessful = false; PertialSchedules::iterator it = pertialSchedules.begin(); while( it != pertialSchedules.end() ) { if( (*it) == pPertialSchedule ) { if( pPertialSchedule->GetTypeSize() == sizeof(char) ) { if( newValue < -128 || 127 < newValue ) { // 範囲外 compiler.errorMessenger.OutputFatalError(); } pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue ); } else if( pPertialSchedule->GetTypeSize() == sizeof(long) ) { pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), static_cast(newValue) ); } else if( pPertialSchedule->GetTypeSize() == sizeof(_int64) ) { pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue ); } else { compiler.errorMessenger.OutputFatalError(); } it = pertialSchedules.erase( it ); delete pPertialSchedule; isSuccessful = true; break; } else { it++; } } if( isSuccessful == false ) { compiler.errorMessenger.OutputFatalError(); } } void CodeGenerator::opfix_offset( const PertialSchedule *pPertialSchedule, long offset ) { bool isSuccessful = false; PertialSchedules::iterator it = pertialSchedules.begin(); while( it != pertialSchedules.end() ) { if( (*it) == pPertialSchedule ) { if( pPertialSchedule->GetTypeSize() == sizeof(long) ) { pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), pNativeCode->GetLong(pPertialSchedule->GetCodePos()) + offset ); } else { compiler.errorMessenger.OutputFatalError(); } it = pertialSchedules.erase( it ); delete pPertialSchedule; isSuccessful = true; break; } else { it++; } } if( isSuccessful == false ) { compiler.errorMessenger.OutputFatalError(); } } // 分岐関連 void CodeGenerator::opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule ) { bool isSuccessful = false; PertialSchedules::iterator it = pertialSchedules.begin(); while( it != pertialSchedules.end() ) { if( (*it) == pPertialSchedule ) { long newValue = pNativeCode->GetSize() - (pPertialSchedule->GetCodePos()+pPertialSchedule->GetTypeSize()); if( pPertialSchedule->GetTypeSize() == sizeof(char) ) { if( newValue < -128 || 127 < newValue ) { // 範囲外 compiler.errorMessenger.OutputFatalError(); } pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), (char)newValue ); } else if( pPertialSchedule->GetTypeSize() == sizeof(long) ) { pNativeCode->Overwrite( pPertialSchedule->GetCodePos(), newValue ); } else { compiler.errorMessenger.OutputFatalError(); } it = pertialSchedules.erase( it ); delete pPertialSchedule; isSuccessful = true; } else { it++; } } if( isSuccessful == false ) { compiler.errorMessenger.OutputFatalError(); } } const PertialSchedule *CodeGenerator::__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { long beginCodePos = pNativeCode->GetSize(); if( opcode == (char)0xEB ) { // jmp命令のとき if( op_size == sizeof(char) ) { pNativeCode->Put( (char)opcode ); } else if( op_size == sizeof(long) ) { pNativeCode->Put( (char)0xE9 ); } else { compiler.errorMessenger.OutputFatalError(); } } else { if( op_size == sizeof(char) ) { pNativeCode->Put( (char)((char)0x70 | opcode) ); } else if( op_size == sizeof(long) ) { pNativeCode->Put( (char)0x0F ); pNativeCode->Put( (char)((char)0x80 | opcode) ); } else { compiler.errorMessenger.OutputFatalError(); } } const PertialSchedule *pPertialSchedule = NULL; if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), op_size ) ); pPertialSchedule = pertialSchedules.back(); } if( isSelfOpcodeOffset ) { // 自分自身の命令サイズを考慮する場合 offset -= ( pNativeCode->GetSize() - beginCodePos ) + op_size; } if( op_size == sizeof(char) ) { pNativeCode->Put( (char)offset ); } else if( op_size == sizeof(long) ) { pNativeCode->Put( offset ); } else { compiler.errorMessenger.OutputFatalError(); } return pPertialSchedule; } const PertialSchedule *CodeGenerator::op_jle( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x0E, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jbe( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x06, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jge( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x0D, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jae( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x03, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jl( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x0C, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jb( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x02, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jg( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x0F, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_ja( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x07, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jne( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x05, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_je( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0x04, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } const PertialSchedule *CodeGenerator::op_jmp( long offset, int op_size, bool isPertialSchedule, bool isSelfOpcodeOffset ) { return __jmp_op_format( (char)0xEB, offset, op_size, isPertialSchedule, isSelfOpcodeOffset ); } void CodeGenerator::op_jmp_continue() { if( GetContinueCodePos() == -1 ) { compiler.errorMessenger.Output(12,"Continue",cp); return; } op_jmp( GetContinueCodePos() - pNativeCode->GetSize(), sizeof(long), false, true ); } void CodeGenerator::op_jmp_exitsub() { // オペコード pNativeCode->Put( (char)0xE9 ); exitSubCodePositions.push_back( pNativeCode->GetSize() ); pNativeCode->Put( (long)0 ); } void CodeGenerator::op_jmp_goto_schedule( const std::string &name, int lineNum, int sourceCodePos ) { // オペコード pNativeCode->Put( (char)0xE9 ); const GotoLabelSchedule *pGotoLabelSchedule = NULL; if( name.size() == 0 ) { pGotoLabelSchedule = new GotoLabelSchedule( name, pNativeCode->GetSize(), sourceCodePos ); } else { pGotoLabelSchedule = new GotoLabelSchedule( name, pNativeCode->GetSize(), sourceCodePos ); } gotoLabelSchedules.push_back( pGotoLabelSchedule ); pertialSchedules.push_back( pGotoLabelSchedule ); pNativeCode->Put( (long)0 ); } void CodeGenerator::op_AddNeedFreeTempStructure( int reg ) { #ifdef _AMD64_ ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// //mov rcx,reg op_mov_RR( REG_RCX, reg ); //call _System_AddNeedFreeTempStructure extern const UserProc *pSub_System_AddNeedFreeTempStructure; op_call( pSub_System_AddNeedFreeTempStructure ); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// #else //push useReg(引き続き利用するため、退避しておく) compiler.codeGenerator.op_push( reg ); //push useReg compiler.codeGenerator.op_push( reg ); //call _System_AddNeedFreeTempStructure extern const UserProc *pSub_System_AddNeedFreeTempStructure; compiler.codeGenerator.op_call( pSub_System_AddNeedFreeTempStructure ); //pop useReg(復元する) compiler.codeGenerator.op_pop( reg ); #endif isNeedFreeTempStructureInCurrentStep = true; } void CodeGenerator::op_FreeTempStructure() { if( !isNeedFreeTempStructureInCurrentStep ) { // 解放の必要はない return; } // call _System_FreeTempStructure extern const UserProc *pSub_System_FreeTempStructure; op_call( pSub_System_FreeTempStructure ); isNeedFreeTempStructureInCurrentStep = false; }