Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1213 lines
40 KiB
C++
1213 lines
40 KiB
C++
|
|
#include "IMCodeGen.h"
|
|
#include "IMCodeUnits.h"
|
|
#include "SymbolTable.h"
|
|
#include "SyntaxTree.h"
|
|
#include <assert.h>
|
|
#include <list>
|
|
#include <map>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// 상수 선언
|
|
|
|
#define MARK_BREAK (IOPCode*)0
|
|
#define MARK_CONTINUE (IOPCode*)1
|
|
#define MARK_RETURN (IOPCode*)2
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// 전역변수
|
|
|
|
static IMCODES * g_pIMCodes = NULL;
|
|
static CSyntaxTree * g_pSyntaxTree = NULL;
|
|
static CSymbolTable * g_pSymbolTable = NULL;
|
|
static FUNCTIONS * g_pFunctions = NULL;
|
|
static int g_iCurrentFuncID = 0;
|
|
|
|
int SWITCHTEMPVAR = 0;
|
|
int FLOATUNIT = 0;
|
|
int FLOATTEMP = 0;
|
|
int STRINGTRUE = 0;
|
|
int STRINGFALSE = 0;
|
|
int CONVERSIONBUFFER = 0;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
void GenerateCode( SNode * pNode, eRegister reg );
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
void HandleMARK( IMCODES::iterator start, IMCODES::iterator end, IOPCode * pJumpSpot, IOPCode * Mark )
|
|
{
|
|
while( start != end )
|
|
{
|
|
if( *start == Mark )
|
|
{
|
|
*start = new COP_jmp( pJumpSpot );
|
|
}
|
|
start++;
|
|
}
|
|
}
|
|
|
|
void GenCode_DataTypeToString( eDataType type, eRegister reg )
|
|
{
|
|
switch( type )
|
|
{
|
|
case T_INT : //int를 문자열로 변환
|
|
g_pIMCodes->push_back( new COP_itoa( reg, VAR(CONVERSIONBUFFER) ) );
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(CONVERSIONBUFFER) ) );
|
|
break;
|
|
|
|
case T_FLOAT : //float를 문자열로 변환
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), reg ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(0), VAR(FLOATTEMP), true ) );
|
|
g_pIMCodes->push_back( new COP_ftoa( reg, VAR(FLOATTEMP), VAR(CONVERSIONBUFFER) ) );
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(CONVERSIONBUFFER) ) );
|
|
break;
|
|
|
|
case T_BOOL : //bool을 문자열로 변환
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( reg, 0 ) );
|
|
//false일 때 점프
|
|
COP_jcc * pJmpSrc1 = new COP_jcc( E );
|
|
g_pIMCodes->push_back( pJmpSrc1 );
|
|
//"true"를 넣고 끝으로 점프
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(STRINGTRUE) ) );
|
|
COP_jmp * pJmpSrc2 = new COP_jmp;
|
|
g_pIMCodes->push_back( pJmpSrc2 );
|
|
//"false"를 넣음.
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc1 ) );
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(STRINGFALSE) ) );
|
|
//끝
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc2 ) );
|
|
break;
|
|
}
|
|
case T_STRING : //변환할 필요가 없으므로 공백
|
|
break;
|
|
|
|
default : //이외의 타입은 나올 수 없음.
|
|
assert( false );
|
|
}
|
|
}
|
|
|
|
void GenCode_Assert( SNode * pNode, eRegister )
|
|
{
|
|
assert( false );
|
|
}
|
|
|
|
void GenCode_Empty( SNode * pNode, eRegister )
|
|
{
|
|
}
|
|
|
|
void GenCode_Error_Statement( SNode * pNode, eRegister )
|
|
{
|
|
ErrorMessage( pNode->m_iLine, "Error Statement" );
|
|
}
|
|
|
|
void GenCode_If_Statement( SNode * pNode, eRegister )
|
|
{
|
|
//1. 비교
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
//2. 0이면 4로 점프
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
COP_jcc * pJmpSrc1 = new COP_jcc( E );
|
|
g_pIMCodes->push_back( pJmpSrc1 );
|
|
//3. 수행문
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], NONE );
|
|
//4. if 끝
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc1 ) );
|
|
}
|
|
|
|
void GenCode_If_Else_Statement( SNode * pNode, eRegister )
|
|
{
|
|
//1. 비교
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX ); //조건절 부분
|
|
//2. 0이면 4로 점프
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
COP_jcc * pJmpSrc1 = new COP_jcc( E );
|
|
g_pIMCodes->push_back( pJmpSrc1 );
|
|
//3. 수행문, 5로 점프
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], NONE ); //then part
|
|
COP_jmp * pJmpSrc2 = new COP_jmp;
|
|
g_pIMCodes->push_back( pJmpSrc2 );
|
|
//4. else 수행
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc1 ) );
|
|
GenerateCode( pNode->m_ArrPtrChilds[2], NONE ); //else part
|
|
//5. endif
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc2 ) ); //endif
|
|
}
|
|
|
|
void GenCode_Switch_Statement( SNode * pNode, eRegister )
|
|
{
|
|
//1.평가
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR( SWITCHTEMPVAR ), ECX ) ); //결과값을 임시 변수에 집어넣고
|
|
//2.모든 case들을 돌며
|
|
SNode * pNodeTemp = pNode->m_ArrPtrChilds[1];
|
|
SNode * pNodeTemp2 = pNodeTemp;
|
|
|
|
g_pIMCodes->push_back( new COP_nop );
|
|
IMCODES::iterator CmpEnd = g_pIMCodes->end();
|
|
CmpEnd--;
|
|
|
|
while( pNodeTemp != NULL )
|
|
{
|
|
if( pNodeTemp->m_eType == TYPE_SWITCH_CASES )
|
|
pNodeTemp2 = pNodeTemp->m_ArrPtrChilds[0];
|
|
else if( pNodeTemp->m_eType == TYPE_CASE_ONE )
|
|
pNodeTemp2 = pNodeTemp;
|
|
else
|
|
break;
|
|
|
|
COP_cmp * p = new COP_cmp( FUNC(0), VAR( SWITCHTEMPVAR ), CONST( pNodeTemp2->m_ArrPtrChilds[0]->m_SymbolID ) );
|
|
//2-1.비교(이전의 비교 뒤에다 삽입)
|
|
g_pIMCodes->insert( CmpEnd, p );
|
|
//2-2.같으면 case statement로 점프
|
|
COP_jcc * pJmpSrc = new COP_jcc( E );
|
|
g_pIMCodes->insert( CmpEnd, pJmpSrc );
|
|
//2-3.case statement 추가
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc ) );
|
|
GenerateCode( pNodeTemp2->m_ArrPtrChilds[1], NONE );
|
|
|
|
pNodeTemp = pNodeTemp->m_ArrPtrChilds[1];
|
|
}
|
|
//3.default로 점프(이전의 비교 뒤에다 삽입)
|
|
COP_jmp * pJmpSrc1 = new COP_jmp;
|
|
g_pIMCodes->insert( CmpEnd, pJmpSrc1 );
|
|
//4.default 추가
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc1 ) );
|
|
GenerateCode( pNode->m_ArrPtrChilds[2], NONE );
|
|
//5.end switch
|
|
COP_jmpmark * pEndSwitch = new COP_jmpmark;
|
|
g_pIMCodes->push_back( pEndSwitch );
|
|
|
|
//6.start switch부터 end switch까지 돌며 break mark를 찾아서 jump to end switch로 교체
|
|
HandleMARK( CmpEnd, g_pIMCodes->end(), pEndSwitch, MARK_BREAK );
|
|
}
|
|
|
|
void GenCode_FirstChild_Generate( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], reg );
|
|
}
|
|
|
|
void GenCode_SecondChild_Generate( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], reg ); //첫번째 자식은 무시
|
|
}
|
|
|
|
void GenCode_TwoChild_Generate( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], reg );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], reg );
|
|
}
|
|
|
|
void GenCode_For_Statement( SNode * pNode, eRegister )
|
|
{
|
|
//1. for_init 수행( 처음 한번만 실행됨 )
|
|
if( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[0] != NULL )
|
|
GenerateCode( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[0], NONE );
|
|
//2. 가감산 부분을 건너뜀
|
|
COP_jmp * pJmpSrc1 = new COP_jmp;
|
|
g_pIMCodes->push_back( pJmpSrc1 );
|
|
//3. for의 가감산 부분 수행
|
|
COP_jmp * pJmpBack = new COP_jmp;
|
|
COP_jmpmark * pJmpBackMark = new COP_jmpmark( pJmpBack );
|
|
g_pIMCodes->push_back( pJmpBackMark );
|
|
if( pNode->m_ArrPtrChilds[0] != NULL )
|
|
GenerateCode( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[2], NONE );
|
|
g_pIMCodes->push_back( new COP_jmpmark( pJmpSrc1 ) );
|
|
//4. for의 비교 수행
|
|
COP_jcc * pJmpToEnd;
|
|
if( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[1] != NULL )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[1], ECX );
|
|
//5. 조건이 거짓일 때 end if로 점프
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
pJmpToEnd = new COP_jcc( E );
|
|
g_pIMCodes->push_back( pJmpToEnd );
|
|
}
|
|
|
|
IMCODES::iterator StatementStart = g_pIMCodes->end();
|
|
StatementStart--;
|
|
//6. statement 수행
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], NONE );
|
|
//7. 3으로 점프
|
|
g_pIMCodes->push_back( pJmpBack );
|
|
|
|
//8. end for
|
|
COP_jmpmark * pEndFor;
|
|
if( pNode->m_ArrPtrChilds[0]->m_ArrPtrChilds[1] != NULL )
|
|
pEndFor = new COP_jmpmark( pJmpToEnd );
|
|
else
|
|
pEndFor = new COP_jmpmark();
|
|
g_pIMCodes->push_back( pEndFor );
|
|
|
|
//break명령들 처리
|
|
HandleMARK( StatementStart, g_pIMCodes->end(), pEndFor, MARK_BREAK );
|
|
//continue명령들 처리
|
|
HandleMARK( StatementStart, g_pIMCodes->end(), pJmpBackMark, MARK_CONTINUE );
|
|
}
|
|
|
|
void GenCode_While_Statement( SNode * pNode, eRegister )
|
|
{
|
|
//0. Begin While
|
|
COP_jmp * pJmpBack = new COP_jmp;
|
|
COP_jmpmark * pJmpBackMark = new COP_jmpmark( pJmpBack );
|
|
g_pIMCodes->push_back( pJmpBackMark );
|
|
//1. 조건 검사
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
//2. 0 (false)이면 end While로 점프
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
COP_jcc * pJmpToEnd = new COP_jcc( E );
|
|
g_pIMCodes->push_back( pJmpToEnd );
|
|
//3. begin statement
|
|
IMCODES::iterator beginStatement = g_pIMCodes->end();
|
|
beginStatement--;
|
|
//4. statement 수행
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], NONE );
|
|
//5. begin While로 점프
|
|
g_pIMCodes->push_back( pJmpBack );
|
|
//6. End While
|
|
COP_jmpmark * pEndWhile = new COP_jmpmark( pJmpToEnd );
|
|
g_pIMCodes->push_back( pEndWhile );
|
|
|
|
//break 처리
|
|
HandleMARK( beginStatement, g_pIMCodes->end(), pEndWhile, MARK_BREAK );
|
|
//continue 처리
|
|
HandleMARK( beginStatement, g_pIMCodes->end(), pJmpBackMark, MARK_CONTINUE );
|
|
}
|
|
|
|
void GenCode_Break_Statement( SNode * pNode, eRegister )
|
|
{
|
|
g_pIMCodes->push_back( MARK_BREAK ); //while, for, switch에서 break명령을 처리할 수 있도록 표시를 남겨둔다.
|
|
}
|
|
void GenCode_Continue_Statement( SNode * pNode, eRegister )
|
|
{
|
|
g_pIMCodes->push_back( MARK_CONTINUE ); //while, for에서 continue명령을 처리할 수 있도록 표시를 남겨둔다.
|
|
}
|
|
|
|
void GenCode_Return_Statement( SNode * pNode, eRegister )
|
|
{
|
|
if( pNode->m_ArrPtrChilds[0] != 0 ) //리턴할 값이 있을 경우에는 EAX에 넣어준다.
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], EAX );
|
|
g_pIMCodes->push_back( MARK_RETURN );
|
|
}
|
|
|
|
void GenCode_Variable( SNode * pNode, eRegister reg )
|
|
{
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
|
|
void GenCode_Init_Declaration( SNode * pNode, eRegister )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_STRING )
|
|
{
|
|
//데이터형에 따라 문자열로 변환.
|
|
GenCode_DataTypeToString( pNode->m_ArrPtrChilds[0]->m_eReturnType, ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_strlen( ECX ) );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, 1 ) );
|
|
g_pIMCodes->push_back( new COP_malloc( EAX ) ); //메모리를 새로 할당.
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), EAX ) );
|
|
g_pIMCodes->push_back( new COP_pop( ECX ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, ECX ) ); //문자열 복사
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ECX ) );
|
|
}
|
|
|
|
}
|
|
|
|
void GenCode_Normal_Declaration( SNode * pNode, eRegister )
|
|
{
|
|
if( pNode->m_eReturnType == T_STRING )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), float(0x0) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Array_Init( SNode * pNode, int childIndex ) //GenCode_Array_Initialize1, 2에서 쓰이는 함수
|
|
{
|
|
SNode * pNodeTemp = pNode->m_ArrPtrChilds[childIndex];
|
|
SNode * pNodeTemp2 = NULL;
|
|
int i = 0, arrSize = g_pSymbolTable->GetCountOfVar( pNode->m_SymbolID );
|
|
|
|
while( pNodeTemp != NULL )
|
|
{
|
|
if( pNodeTemp->m_eType == TYPE_INITIALIZER_LIST )
|
|
pNodeTemp2 = pNodeTemp->m_ArrPtrChilds[0];
|
|
else
|
|
pNodeTemp2 = pNodeTemp;
|
|
|
|
GenerateCode( pNodeTemp2, ECX );
|
|
|
|
if( pNode->m_eReturnType == T_STRING )
|
|
{
|
|
//데이터형에 따라 문자열로 변환.
|
|
GenCode_DataTypeToString( pNodeTemp2->m_eReturnType, ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_strlen( ECX ) );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, 1 ) );
|
|
g_pIMCodes->push_back( new COP_malloc( EAX ) ); //메모리를 새로 할당.
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), i, EAX ) );
|
|
g_pIMCodes->push_back( new COP_pop( ECX ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, ECX ) ); //문자열 복사
|
|
}
|
|
else
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), i, ECX ) );
|
|
|
|
if( pNodeTemp->m_eType == TYPE_INITIALIZER_LIST )
|
|
{
|
|
if( ++i >= arrSize )
|
|
break;
|
|
pNodeTemp = pNodeTemp->m_ArrPtrChilds[1];
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GenCode_Array_Initialize( SNode * pNode, eRegister )
|
|
{
|
|
GenCode_Array_Init( pNode, 0 );
|
|
}
|
|
|
|
void GenCode_Array_Initialize2( SNode * pNode, eRegister )
|
|
{
|
|
GenCode_Array_Init( pNode, 1 );
|
|
}
|
|
|
|
void GenCode_Function_Declaration( SNode * pNode, eRegister )
|
|
{
|
|
IMCODES * pNewFunc = new IMCODES;
|
|
if( g_pFunctions->insert( FUNCTIONS::value_type( pNode->m_SymbolID, pNewFunc ) ).second == false )
|
|
ErrorMessage( pNode->m_iLine, "같은 함수를 두 번 만들려고 시도했습니다." );
|
|
|
|
SFuncType type = g_pSymbolTable->GetTypeOfFunc( pNode->m_SymbolID );
|
|
int emptyCodeSize = type.GetArgCount() * 3 + 5;
|
|
|
|
pNewFunc->push_back( new COP_push( EBP ) );
|
|
pNewFunc->push_back( new COP_mov( EBP, ESP ) );
|
|
|
|
for( int i = 0; i < emptyCodeSize; i++ )
|
|
pNewFunc->push_back( new COP_nop );
|
|
|
|
pNewFunc->push_back( new COP_mov( ESP, EBP ) );
|
|
pNewFunc->push_back( new COP_pop( EBP ) );
|
|
pNewFunc->push_back( new COP_ret );
|
|
}
|
|
|
|
void GenCode_Function_Definition( SNode * pNode, eRegister )
|
|
{
|
|
IMCODES * pNewFunc = new IMCODES;
|
|
if( g_pFunctions->insert( FUNCTIONS::value_type( pNode->m_SymbolID, pNewFunc ) ).second == false )
|
|
ErrorMessage( pNode->m_iLine, "같은 함수를 두 번 만들려고 시도했습니다." );
|
|
|
|
swap( pNewFunc, g_pIMCodes ); //GenerateCode가 새로 만든 함수 코드 컨테이너에 코드를 생성하도록..
|
|
g_iCurrentFuncID = pNode->m_SymbolID;
|
|
|
|
//함수 머리
|
|
g_pIMCodes->push_back( new COP_push( EBP ) );
|
|
g_pIMCodes->push_back( new COP_mov( EBP, ESP ) );
|
|
|
|
int varSize = g_pSymbolTable->GetLocalVarSize( pNode->m_SymbolID );
|
|
if( varSize )
|
|
g_pIMCodes->push_back( new COP_sub( ESP, varSize ) );
|
|
|
|
//함수의 변수 크기를 세는 기능이 있어야 한다.
|
|
|
|
IMCODES::iterator beginFunc = g_pIMCodes->end();
|
|
beginFunc--;
|
|
if( pNode->m_ArrPtrChilds[0] != NULL )
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], NONE );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], NONE );
|
|
|
|
IMCODES::iterator endFunc = g_pIMCodes->end();
|
|
|
|
//함수 꼬리
|
|
COP_jmpmark * returnSpot = new COP_jmpmark;
|
|
g_pIMCodes->push_back( returnSpot );
|
|
g_pIMCodes->push_back( new COP_mov( ESP, EBP ) );
|
|
g_pIMCodes->push_back( new COP_pop( EBP ) );
|
|
g_pIMCodes->push_back( new COP_ret );
|
|
|
|
HandleMARK( beginFunc, endFunc, returnSpot, MARK_RETURN );
|
|
|
|
swap( pNewFunc, g_pIMCodes );
|
|
g_iCurrentFuncID = 0;
|
|
}
|
|
|
|
void GenCode_Constant_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( reg, CONST( pNode->m_SymbolID ) ) );
|
|
}
|
|
|
|
void GenCode_Assignment_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_STRING )
|
|
{
|
|
//데이터형에 따라 문자열로 변환.
|
|
GenCode_DataTypeToString( pNode->m_ArrPtrChilds[0]->m_eReturnType, ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_strlen( ECX ) );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, 1 ) );
|
|
g_pIMCodes->push_back( new COP_malloc( EAX ) ); //메모리를 새로 할당.
|
|
g_pIMCodes->push_back( new COP_mov( EBX, EAX ) );
|
|
//이전 버퍼를 지운다.
|
|
g_pIMCodes->push_back( new COP_free( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), EBX ) );
|
|
g_pIMCodes->push_back( new COP_pop( ECX ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EBX, ECX ) ); //문자열 복사
|
|
if( reg != NONE && reg != EAX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EAX ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ECX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_OR_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 1 ) );
|
|
//첫번째 조건이 참이면 결과값에 참을 넣는 곳으로 점프
|
|
COP_jcc * jmpSrc = new COP_jcc( E );
|
|
g_pIMCodes->push_back( jmpSrc );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
g_pIMCodes->push_back( new COP_cmp( EDX, 1 ) );
|
|
//두번째 조건이 참이면 결과값에 참을 넣는 곳으로 점프
|
|
COP_jcc * jmpSrc2 = new COP_jcc( E );
|
|
g_pIMCodes->push_back( jmpSrc2 );
|
|
//둘 다 거짓이면 결과값에 거짓을 넣고 끝으로 점프
|
|
g_pIMCodes->push_back( new COP_mov( reg, 0 ) );
|
|
COP_jmp * jmpSrc3 = new COP_jmp;
|
|
g_pIMCodes->push_back( jmpSrc3 );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc ) );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc2 ) );
|
|
//결과값에 참을 넣고 끝냄
|
|
g_pIMCodes->push_back( new COP_mov( reg, 1 ) );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc3 ) );
|
|
}
|
|
|
|
void GenCode_AND_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
//첫번째 조건이 거짓이면 결과값에 거짓을 넣는 곳으로 점프
|
|
COP_jcc * jmpSrc = new COP_jcc( E );
|
|
g_pIMCodes->push_back( jmpSrc );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
g_pIMCodes->push_back( new COP_cmp( EDX, 0 ) );
|
|
//두번째 조건이 거짓이면 결과값에 거짓을 넣는 곳으로 점프
|
|
COP_jcc * jmpSrc2 = new COP_jcc( E );
|
|
g_pIMCodes->push_back( jmpSrc2 );
|
|
//둘 다 참이면 결과값에 참을 넣고 끝으로 점프
|
|
g_pIMCodes->push_back( new COP_mov( reg, 1 ) );
|
|
COP_jmp * jmpSrc3 = new COP_jmp;
|
|
g_pIMCodes->push_back( jmpSrc3 );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc ) );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc2 ) );
|
|
//결과값에 거짓을 넣고 끝냄
|
|
g_pIMCodes->push_back( new COP_mov( reg, 0 ) );
|
|
g_pIMCodes->push_back( new COP_jmpmark( jmpSrc3 ) );
|
|
}
|
|
|
|
void GenCode_NOT_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, 0 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( E, reg ) );
|
|
}
|
|
|
|
void GenCode_Equality_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_STRING )
|
|
{
|
|
g_pIMCodes->push_back( new COP_strcmp( ECX, EDX ) );
|
|
g_pIMCodes->push_back( new COP_cmp( EAX, 0 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( E, reg ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( E, reg ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_NotEqual_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_STRING )
|
|
{
|
|
g_pIMCodes->push_back( new COP_strcmp( ECX, EDX ) );
|
|
g_pIMCodes->push_back( new COP_cmp( EAX, 0 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( NE, reg ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( NE, reg ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_LessThan_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( L, reg ) );
|
|
}
|
|
else //float
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fcomp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fnstsw_ax );
|
|
g_pIMCodes->push_back( new COP_test_ah( 1 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( NE, reg ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_MoreThan_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( G, reg ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fcomp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fnstsw_ax );
|
|
g_pIMCodes->push_back( new COP_test_ah( 65 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( E, reg ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_LessThanEqual_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( LE, reg ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fcomp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fnstsw_ax );
|
|
g_pIMCodes->push_back( new COP_test_ah( 65 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( NE, reg ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_MoreThanEqual_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_ArrPtrChilds[0]->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_cmp( ECX, EDX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( GE, reg ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fcomp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fnstsw_ax );
|
|
g_pIMCodes->push_back( new COP_test_ah( 1 ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_setcc( E, reg ) );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void GenCode_Addition_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
g_pIMCodes->push_back( new COP_add( ECX, EDX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
else if( pNode->m_eReturnType == T_FLOAT )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fadd( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(FLOATTEMP) ) );
|
|
}
|
|
else //string
|
|
{
|
|
g_pIMCodes->push_back( new COP_push( ESI ) );
|
|
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], EAX );
|
|
GenCode_DataTypeToString( pNode->m_ArrPtrChilds[0]->m_eReturnType, EAX );
|
|
g_pIMCodes->push_back( new COP_push( EAX ) );
|
|
|
|
//문자열 길이 계산
|
|
g_pIMCodes->push_back( new COP_strlen( EAX ) );
|
|
g_pIMCodes->push_back( new COP_mov( EDI, EAX ) );
|
|
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EBX );
|
|
GenCode_DataTypeToString( pNode->m_ArrPtrChilds[1]->m_eReturnType, EBX );
|
|
|
|
g_pIMCodes->push_back( new COP_strlen( EBX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, EDI ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, 1 ) );
|
|
//메모리를 새로 할당
|
|
g_pIMCodes->push_back( new COP_malloc( EAX ) );
|
|
//문자열 복사
|
|
g_pIMCodes->push_back( new COP_pop( ESI ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, ESI ) );
|
|
g_pIMCodes->push_back( new COP_mov( ESI, EAX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, EDI ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, EBX ) );
|
|
//새로 할당된 메모리 주소를 대상 레지스터에 대입
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ESI ) );
|
|
|
|
g_pIMCodes->push_back( new COP_pop( ESI ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Subtraction_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_sub( ECX, EDX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fsub( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(FLOATTEMP) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Multiplication_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], EDX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_imul( ECX, EDX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EDX ) );
|
|
g_pIMCodes->push_back( new COP_fmul( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(FLOATTEMP) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Division_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], EAX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_idiv( ECX ) );
|
|
if( reg != NONE && reg != EAX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EAX ) );
|
|
}
|
|
else //float
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), EAX ) );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fdiv( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(0), VAR(FLOATTEMP) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(0), VAR(FLOATTEMP) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Reminder_Expression( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], EAX );
|
|
GenerateCode( pNode->m_ArrPtrChilds[1], ECX );
|
|
g_pIMCodes->push_back( new COP_idiv( ECX ) );
|
|
if( reg != NONE && reg != EDX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EDX ) );
|
|
}
|
|
|
|
void GenCode_Compound_Addition( SNode * pNode, eRegister reg )
|
|
{
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_mov( EDX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_add( EDX, ECX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), EDX ) );
|
|
if( reg != NONE && reg != EDX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EDX ) );
|
|
}
|
|
else if( pNode->m_eReturnType == T_FLOAT )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fadd( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
else //string
|
|
{
|
|
//문자열 길이 계산
|
|
g_pIMCodes->push_back( new COP_strlen( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( EBX, EAX ) );
|
|
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
//데이터 타입에 따라 문자열로 변환
|
|
GenCode_DataTypeToString( pNode->m_ArrPtrChilds[0]->m_eReturnType, ECX );
|
|
|
|
g_pIMCodes->push_back( new COP_strlen( ECX ) );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, EBX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, 1 ) );
|
|
//메모리를 새로 할당
|
|
g_pIMCodes->push_back( new COP_malloc( EAX ) );
|
|
//문자열 복사
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_pop( ECX ) );
|
|
g_pIMCodes->push_back( new COP_push( EAX ) );
|
|
g_pIMCodes->push_back( new COP_add( EAX, EBX ) );
|
|
g_pIMCodes->push_back( new COP_strcpy( EAX, ECX ) );
|
|
//이전 버퍼를 지우고 새로 할당된 메모리 주소를 대상 변수에 대입
|
|
g_pIMCodes->push_back( new COP_free( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_pop( EAX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), EAX ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EAX ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Compound_Subtraction( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( EDX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_sub( EDX, ECX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), EDX ) );
|
|
if( reg != NONE && reg != EDX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EDX ) );
|
|
}
|
|
else
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fsub( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Compound_Multiplication( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( EDX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_imul( EDX, ECX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), EDX ) );
|
|
if( reg != NONE && reg != EDX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EDX ) );
|
|
}
|
|
else //float
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fmul( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Compound_Division( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( EAX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_idiv( ECX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), EAX ) );
|
|
if( reg != NONE && reg != EAX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EAX ) );
|
|
}
|
|
else //float
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(0), VAR(FLOATTEMP), ECX ) );
|
|
g_pIMCodes->push_back( new COP_fdiv( FUNC(0), VAR(FLOATTEMP) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Compound_Reminder( SNode * pNode, eRegister reg )
|
|
{
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_mov( EAX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_idiv( ECX ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), EDX ) );
|
|
if( reg != NONE && reg != EDX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EDX ) );
|
|
}
|
|
|
|
void GenCode_PrefixIncrement( SNode * pNode, eRegister reg )
|
|
{
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( ECX, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_add( ECX, 1 ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ECX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
else
|
|
{
|
|
const char * str = g_pSymbolTable->GetNameOfVar( pNode->m_SymbolID );
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_fadd( FUNC(0), VAR(FLOATUNIT) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_PrefixDecrement( SNode * pNode, eRegister reg )
|
|
{
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_mov( ECX, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_sub( ECX, 1 ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ECX ) );
|
|
if( reg != NONE && reg != ECX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, ECX ) );
|
|
}
|
|
else //float일 때
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_fsub( FUNC(0), VAR(FLOATUNIT) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_Array_Indexing( SNode * pNode, eRegister reg )
|
|
{
|
|
g_pIMCodes->push_back( new COP_push( ESI ) );
|
|
|
|
eRegister StoreReg = reg == ECX ? EDX : ECX;
|
|
GenerateCode( pNode->m_ArrPtrChilds[0], StoreReg );
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID), StoreReg ) );
|
|
|
|
g_pIMCodes->push_back( new COP_pop( ESI ) );
|
|
}
|
|
|
|
void GenCode_Function_Call( SNode * pNode, eRegister reg )
|
|
{
|
|
//인자들을 모두 스택에 push한다.
|
|
SNode * pNodeTemp = pNode->m_ArrPtrChilds[0];
|
|
int i = 0;
|
|
|
|
while( pNodeTemp != NULL )
|
|
{
|
|
if( pNodeTemp->m_eType == TYPE_EXPRESSION_LIST )
|
|
{
|
|
GenerateCode( pNodeTemp->m_ArrPtrChilds[0], ECX );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
i++;
|
|
pNodeTemp = pNodeTemp->m_ArrPtrChilds[1];
|
|
}
|
|
else
|
|
{
|
|
GenerateCode( pNodeTemp, ECX );
|
|
g_pIMCodes->push_back( new COP_push( ECX ) );
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_pIMCodes->push_back( new COP_call( FUNC(pNode->m_SymbolID), pNode->m_iLine ) );
|
|
//스택에 넣었던 인자들을 모두 pop한다.( Stack Pointer를 옮김으로써.. )
|
|
g_pIMCodes->push_back( new COP_add( ESP, i*4 ) );
|
|
if( reg != NONE && reg != EAX )
|
|
g_pIMCodes->push_back( new COP_mov( reg, EAX ) );
|
|
|
|
}
|
|
|
|
void GenCode_PostfixIncrement( SNode * pNode, eRegister reg )
|
|
{
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_push( ESI ) );
|
|
|
|
assert( reg != ESI );
|
|
g_pIMCodes->push_back( new COP_mov( ESI, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_add( ESI, 1 ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ESI ) );
|
|
|
|
g_pIMCodes->push_back( new COP_pop( ESI ) );
|
|
}
|
|
else //float 일 때
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_fadd( FUNC(0), VAR(FLOATUNIT) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
void GenCode_PostfixDecrement( SNode * pNode, eRegister reg )
|
|
{
|
|
if( reg != NONE )
|
|
g_pIMCodes->push_back( new COP_mov( reg, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
|
|
if( pNode->m_eReturnType == T_INT )
|
|
{
|
|
g_pIMCodes->push_back( new COP_push( ESI ) );
|
|
|
|
assert( reg != ESI );
|
|
g_pIMCodes->push_back( new COP_mov( ESI, FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ) ) );
|
|
g_pIMCodes->push_back( new COP_sub( ESI, 1 ) );
|
|
g_pIMCodes->push_back( new COP_mov( FUNC(g_iCurrentFuncID), VAR( pNode->m_SymbolID ), ESI ) );
|
|
|
|
g_pIMCodes->push_back( new COP_pop( ESI ) );
|
|
}
|
|
else //float일 경우
|
|
{
|
|
g_pIMCodes->push_back( new COP_fld( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
g_pIMCodes->push_back( new COP_fsub( FUNC(0), VAR(FLOATUNIT) ) );
|
|
g_pIMCodes->push_back( new COP_fstp( FUNC(g_iCurrentFuncID), VAR(pNode->m_SymbolID) ) );
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
typedef void (*GENCODE)( SNode * pNode, eRegister );
|
|
|
|
GENCODE g_GenCodeFunctions[] = {
|
|
|
|
GenCode_TwoChild_Generate, //TYPE_STATEMENT_LIST
|
|
GenCode_Empty,
|
|
GenCode_Error_Statement,
|
|
GenCode_FirstChild_Generate, //TYPE_EXPRESSION
|
|
GenCode_If_Statement,
|
|
GenCode_If_Else_Statement,
|
|
GenCode_Switch_Statement,
|
|
GenCode_Assert, //TYPE_SWITCH_CASES
|
|
GenCode_Assert, //TYPE_CASE_ONE
|
|
GenCode_FirstChild_Generate, //TYPE_DEFAULT
|
|
GenCode_For_Statement,
|
|
GenCode_While_Statement,
|
|
GenCode_Assert, //TYPE_FOR_EXPRESSION
|
|
GenCode_Break_Statement,
|
|
GenCode_Continue_Statement,
|
|
GenCode_Return_Statement,
|
|
GenCode_SecondChild_Generate,
|
|
GenCode_Assert, //TYPE_SPECIFIER_VOID
|
|
GenCode_Assert, //TYPE_SPECIFIER_INT
|
|
GenCode_Assert, //TYPE_SPECIFIER_FLOAT
|
|
GenCode_Assert, //TYPE_SPECIFIER_BOOL
|
|
GenCode_Assert, //TYPE_SPECIFIER_STRING
|
|
GenCode_Variable,
|
|
GenCode_TwoChild_Generate, //TYPE_DECLARATOR_LIST
|
|
GenCode_Init_Declaration,
|
|
GenCode_Normal_Declaration,
|
|
GenCode_Array_Initialize,
|
|
GenCode_Array_Initialize2,
|
|
GenCode_Empty,
|
|
GenCode_Function_Declaration,
|
|
GenCode_TwoChild_Generate, //TYPE_INITIALIZER_LIST
|
|
GenCode_TwoChild_Generate, //TYPE_ARGUMENT_DECLARATION_LIST
|
|
GenCode_Empty,
|
|
GenCode_Function_Definition,
|
|
GenCode_Constant_Expression,
|
|
GenCode_TwoChild_Generate, //TYPE_EXPRESSION_LIST
|
|
GenCode_Assignment_Expression,
|
|
GenCode_OR_Expression,
|
|
GenCode_AND_Expression,
|
|
GenCode_NOT_Expression,
|
|
GenCode_Equality_Expression,
|
|
GenCode_NotEqual_Expression,
|
|
GenCode_LessThan_Expression,
|
|
GenCode_MoreThan_Expression,
|
|
GenCode_LessThanEqual_Expression,
|
|
GenCode_MoreThanEqual_Expression,
|
|
GenCode_Addition_Expression,
|
|
GenCode_Subtraction_Expression,
|
|
GenCode_Multiplication_Expression,
|
|
GenCode_Division_Expression,
|
|
GenCode_Reminder_Expression,
|
|
GenCode_Compound_Addition,
|
|
GenCode_Compound_Subtraction,
|
|
GenCode_Compound_Multiplication,
|
|
GenCode_Compound_Division,
|
|
GenCode_Compound_Reminder,
|
|
GenCode_PrefixIncrement,
|
|
GenCode_PrefixDecrement,
|
|
GenCode_Array_Indexing,
|
|
GenCode_Function_Call,
|
|
GenCode_PostfixIncrement,
|
|
GenCode_PostfixDecrement
|
|
};
|
|
|
|
void GenerateCode( SNode * pNode, eRegister reg )
|
|
{
|
|
(g_GenCodeFunctions[pNode->m_eType])( pNode, reg );
|
|
}
|
|
|
|
void GenerateCode( CSyntaxTree & rSyntaxTree, IMCODES & rIMCodes, FUNCTIONS & rFunctions )
|
|
{
|
|
g_pSyntaxTree = &rSyntaxTree;
|
|
g_pSymbolTable = rSyntaxTree.GetSymbolTable();
|
|
g_pIMCodes = &rIMCodes;
|
|
g_pFunctions = &rFunctions;
|
|
|
|
//스크립트 시스템 변수를 만든다.
|
|
SWITCHTEMPVAR = g_pSymbolTable->AddVar( SYSVAR_SWITCHTEMP, T_INT );
|
|
assert( SWITCHTEMPVAR != 0 );
|
|
FLOATUNIT = g_pSymbolTable->AddVar( SYSVAR_FLOATUNIT, T_FLOAT );
|
|
assert( FLOATUNIT != 0 );
|
|
FLOATTEMP = g_pSymbolTable->AddArrVar( SYSVAR_FLOATTEMP, T_FLOAT, 2 );
|
|
assert( FLOATTEMP != 0 );
|
|
STRINGTRUE = g_pSymbolTable->AddVar( SYSVAR_TRUE, T_STRING );
|
|
assert( STRINGTRUE != 0 );
|
|
STRINGFALSE = g_pSymbolTable->AddVar( SYSVAR_FALSE, T_STRING );
|
|
assert( STRINGFALSE != 0 );
|
|
CONVERSIONBUFFER = g_pSymbolTable->AddVar( SYSVAR_CONVBUFFER, T_STRING );
|
|
assert( CONVERSIONBUFFER != 0 );
|
|
|
|
//코드 생성.
|
|
GenerateCode( rSyntaxTree.GetRoot(), NONE );
|
|
|
|
//처리되지 않은 break, continue문을 처리한다.
|
|
for( IMCODES::iterator i = g_pIMCodes->begin(); i != g_pIMCodes->end(); i++ )
|
|
{
|
|
if( *i == MARK_BREAK || *i == MARK_CONTINUE )
|
|
*i = new COP_nop;
|
|
}
|
|
|
|
IMCODES::iterator begin = g_pIMCodes->begin();
|
|
//main 함수 머리
|
|
for( int j = 0; j < 3; j++ )
|
|
g_pIMCodes->insert( begin, new COP_nop );
|
|
|
|
g_pIMCodes->insert( begin, new COP_push( EBP ) );
|
|
g_pIMCodes->insert( begin, new COP_mov( EBP, ESP ) );
|
|
|
|
//main 함수 꼬리
|
|
COP_jmpmark * returnSpot = new COP_jmpmark;
|
|
g_pIMCodes->push_back( returnSpot );
|
|
g_pIMCodes->push_back( new COP_mov( ESP, EBP ) );
|
|
g_pIMCodes->push_back( new COP_pop( EBP ) );
|
|
g_pIMCodes->push_back( new COP_ret );
|
|
|
|
for( int j = 0; j < 3; j++ )
|
|
g_pIMCodes->push_back( new COP_int3 );
|
|
|
|
HandleMARK( begin, g_pIMCodes->end(), returnSpot, MARK_RETURN );
|
|
|
|
g_pSyntaxTree = NULL;
|
|
g_pSymbolTable = NULL;
|
|
g_pIMCodes = NULL;
|
|
g_pFunctions = NULL;
|
|
} |