|
|
//
// Copyright (c) Microsoft Corporation 1995
//
// codegen.c
//
// This file contains the code-generating functions.
//
// The "code" is actually just an intermediate representation.
// Currently this is an array of ASTs.
//
// History:
// 06-18-95 ScottH Created
//
#include "proj.h"
#include "rcids.h"
RES PRIVATE Stmt_Codegen(PSTMT this, PASTEXEC pastexec, PSYMTAB pst);
/*----------------------------------------------------------
Purpose: Generate code for the 'while' statement
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE WhileStmt_Codegen( PSTMT this, PASTEXEC pastexec, PSYMTAB pst) { RES res; LPSTR pszTop; LPSTR pszEnd;
ASSERT(this); ASSERT(pastexec); ASSERT(AT_WHILE_STMT == Ast_GetType(this));
pszTop = WhileStmt_GetTopLabel(this); pszEnd = WhileStmt_GetEndLabel(this);
res = Astexec_InsertLabel(pastexec, pszTop, pst); if (RSUCCEEDED(res)) { // add the 'while' statement for the test expression
res = Astexec_Add(pastexec, this); if (RSUCCEEDED(res)) { // add the statements in the statement block
DWORD i; DWORD cstmts; HPA hpaStmts = WhileStmt_GetStmtBlock(this);
res = RES_OK;
cstmts = PAGetCount(hpaStmts);
// Add each statement
for (i = 0; i < cstmts; i++) { PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, pst); if (RFAILED(res)) break; }
if (RSUCCEEDED(res)) { // add the end label
res = Astexec_InsertLabel(pastexec, pszEnd, pst); } } }
return res; }
/*----------------------------------------------------------
Purpose: Generate code for the 'if' statement
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE IfStmt_Codegen( PSTMT this, PASTEXEC pastexec, PSYMTAB pst) { RES res; LPSTR pszElse; LPSTR pszEnd;
ASSERT(this); ASSERT(pastexec); ASSERT(AT_IF_STMT == Ast_GetType(this));
pszElse = IfStmt_GetElseLabel(this); pszEnd = IfStmt_GetEndLabel(this);
// add the 'if' statement for the test expression
res = Astexec_Add(pastexec, this); if (RSUCCEEDED(res)) { // add the statements in the 'then' statement block
DWORD i; DWORD cstmts; HPA hpaStmts = IfStmt_GetStmtBlock(this);
res = RES_OK;
cstmts = PAGetCount(hpaStmts);
// Add each statement
for (i = 0; i < cstmts; i++) { PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, pst); if (RFAILED(res)) break; }
if (RSUCCEEDED(res)) { // add the else label
res = Astexec_InsertLabel(pastexec, pszElse, pst); } }
return res; }
/*----------------------------------------------------------
Purpose: Generate code for the label statement
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE LabelStmt_Codegen( PSTMT this, PASTEXEC pastexec, PSYMTAB pst) { LPSTR pszIdent;
ASSERT(this); ASSERT(pastexec); ASSERT(AT_LABEL_STMT == Ast_GetType(this));
pszIdent = LabelStmt_GetIdent(this);
return Astexec_InsertLabel(pastexec, pszIdent, pst); }
/*----------------------------------------------------------
Purpose: Generate code for the 'set' statement
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE SetStmt_Codegen( PSTMT this, PASTEXEC pastexec, PSYMTAB pst) { RES res = RES_OK;
ASSERT(this); ASSERT(pastexec); ASSERT(AT_SET_STMT == Ast_GetType(this));
switch (SetStmt_GetType(this)) { case ST_IPADDR: case ST_PORT: case ST_SCREEN: res = Astexec_Add(pastexec, this); break;
default: ASSERT(0); res = RES_E_INVALIDPARAM; break; }
return res; }
/*----------------------------------------------------------
Purpose: Generate code for a statement
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE Stmt_Codegen( PSTMT this, PASTEXEC pastexec, PSYMTAB pst) { RES res;
ASSERT(this); ASSERT(pastexec);
switch (Ast_GetType(this)) { case AT_ENTER_STMT: case AT_LEAVE_STMT: case AT_HALT_STMT: case AT_TRANSMIT_STMT: case AT_WAITFOR_STMT: case AT_DELAY_STMT: case AT_GOTO_STMT: case AT_ASSIGN_STMT: res = Astexec_Add(pastexec, this); break;
case AT_WHILE_STMT: res = WhileStmt_Codegen(this, pastexec, pst); break;
case AT_IF_STMT: res = IfStmt_Codegen(this, pastexec, pst); break;
case AT_SET_STMT: res = SetStmt_Codegen(this, pastexec, pst); break;
case AT_LABEL_STMT: res = LabelStmt_Codegen(this, pastexec, pst); break;
default: ASSERT(0); res = RES_E_INVALIDPARAM; break; }
return res; }
/*----------------------------------------------------------
Purpose: Generate code for a procedure declaration.
Returns: RES_OK or some error result
Cond: -- */ RES PRIVATE ProcDecl_Codegen( PPROCDECL this, PASTEXEC pastexec) { RES res = RES_OK; DWORD i; DWORD cstmts;
ASSERT(this); ASSERT(pastexec);
cstmts = PAGetCount(this->hpaStmts);
// Generate for each statement
for (i = 0; i < cstmts; i++) { PSTMT pstmt = PAFastGetPtr(this->hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, this->pst); if (RFAILED(res)) break; }
return res; }
/*----------------------------------------------------------
Purpose: Find the proc decl that has the given identifier.
Returns: TRUE (if found)
Cond: -- */ BOOL PRIVATE FindProc( PMODULEDECL pmd, LPCSTR pszIdent, PPROCDECL * ppprocdecl) { DWORD i; DWORD cprocs = PAGetCount(pmd->hpaProcs);
*ppprocdecl = NULL;
for (i = 0; i < cprocs; i++) { PPROCDECL pprocdecl = PAFastGetPtr(pmd->hpaProcs, i);
if (IsSzEqualC(ProcDecl_GetIdent(pprocdecl), pszIdent)) { *ppprocdecl = pprocdecl; break; } }
return NULL != *ppprocdecl; }
/*----------------------------------------------------------
Purpose: Generate code for the module declaration.
Returns: RES_OK or some error result
Cond: -- */ RES PUBLIC ModuleDecl_Codegen( PMODULEDECL this, PASTEXEC pastexec) { RES res = RES_OK; DWORD i; DWORD cprocs; PPROCDECL ppdMain;
ASSERT(this); ASSERT(pastexec);
TRACE_MSG(TF_GENERAL, "Generating code...");
cprocs = PAGetCount(this->hpaProcs);
// Generate code for the main proc first.
if (FindProc(this, "main", &ppdMain)) { res = ProcDecl_Codegen(ppdMain, pastexec); if (RSUCCEEDED(res)) { // Generate code for the rest of the procs
for (i = 0; i < cprocs; i++) { PPROCDECL pprocdecl = PAFastGetPtr(this->hpaProcs, i);
if (pprocdecl != ppdMain) { res = ProcDecl_Codegen(pprocdecl, pastexec); if (RFAILED(res)) break; } } } } else { // Typechecking should have guaranteed that the main
// proc was here
ASSERT(0); res = RES_E_FAIL; }
return res; }
|