⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 code.cpp

📁 一个c语言的编译器的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This file do the most terrible job: code generation
// It's really a challenging job, you must design carefully
// all the time
//
// Written by bood, boodweb@163.com, http://boodweb.126.com
// 2004-08-06

// Now generating the assemble codes of CPU above pentium 386
// and with a simple I/O library & an assembler like MASM/TASM
// an executable file is avaiable
// bood, 2004-08-13

// Generate code for initializations
//
// Bug fixed:
// SP/BP is used instead of ESP/EBP, for dos mode of windows,
// operators like POP/PUSH are with SP/BP, use of ESP can cause
// overflow exception
// by bood, 2005-01-17

// Generate external symbol declarations for function declarations
// without definitions, so that multi-file compilation supported
// Function 'genExternSymbol' does the main job
//
// by bood, 2005-03-13

#pragma warning(disable:4786)

#include <string>
#include <sstream>
#include "global.h"
#include "symtable.h"
#include "code.h"
#include "util.h"
#include "analyze.h"

// Define the registers
#define STACK 100
#define NONE -1
#define EAX 0
#define EBX 1
#define ECX 2
#define EDX 3
#define SP  4
#define BP  5
#define EBP 6
#define CS  7
#define DS  8
#define ES  9
#define SS  10

using namespace std;

static string regs[]={"EAX","EBX","ECX","EDX","SP","BP","EBP",
                    "CS","DS","ES","SS"};
static int labelNumber = 0;     //for jump use
//static string FuncName;

void emitComment(const string &comment, int tabs = 0)
{
    if(tabs) fcode<<'\t';
    fcode<<';'<<comment<<'\n';
}

// emit a jump label: L<number>
string emitLabel(int tabs = 0)
{
    ostringstream os;
    os<<'L'<<labelNumber++;
    return os.str();
}

// just emit a line with anything, this can simplify
// the calling procedure
void emitLine(const string &code, int tabs = 0)
{
    if(tabs) fcode<<'\t';
    fcode<<code<<'\n';
}

// just emit a line of code with anything, just like
// emitLine except this keeps a tab in front by default
void emitCode(const string &code, int tabs = 1)
{
    if(tabs) fcode<<'\t';
    fcode<<code<<'\n';
}

// emit the global variable declaration
void emitDeclare(const string &name, int space, int tabs = 1)
{
    if(tabs) fcode<<'\t';
    fcode<<'_'<<name<<"\tdd\t"<<space<<" dup(0)\n";
}

// emit an line of code with no operand
void emitNoOprand(const string &op, int tabs = 1)
{
    if(tabs) fcode<<'\t';
    fcode<<op<<'\n';
}

// emit an line of code with one operand
void emitOneOprand(const string &op, const string &imm, int tabs = 1)
{
    if(tabs) fcode<<'\t';
    fcode<<op<<'\t'
        <<imm<<'\n';
}

// emit an line of code with two operands
void emitTwoOprand(const string &op,
                   const string &op1, const string &op2,
                   int tabs = 1)
{
    if(tabs) fcode<<'\t';
    fcode<<op<<'\t'
        <<op1<<','
        <<op2<<'\n';
}

// emit a memory address like [base+index*scale+disp]
string memAddr(int base, int index, int scale, const string& disp = "")
{
    ostringstream os;
    os<<'[';
    if(base != NONE) os<<regs[base];
    if(index != NONE) {
        if(base != NONE) os<<'+';
        os<<regs[index];
    }
    if(scale != 0) {os<<'*';os<<scale;}
    if(!disp.empty()) {os<<'+'<<disp;}
    os<<']';
    //if(mem=="[]") GenError("Empty memory address generated.");
    return os.str();
}

// same as above except the last parameter
string memAddr(int base, int index, int scale, int disp = 0)
{
    ostringstream os;
    os<<'[';
    if(base != NONE) os<<regs[base];
    if(index != NONE) {
        if(base != NONE) os<<'+';
        os<<regs[index];
    }
    if(scale != 0) {os<<'*';os<<scale;}
    if(disp != 0) {os<<'+'<<disp;}
    os<<']';
    return os.str();
}

// emit code for temp result
// result is pre-saved in EAX
void emitTemp(int tmpR)
{
	if(tmpR==STACK){
		emitCode("PUSH EAX");
	}
    else if(tmpR==NONE) return;
	else if(tmpR!=EAX){
		emitTwoOprand("MOV", regs[tmpR], regs[EAX]);
	}
	return;
}

//emit code for I/O of variable
//loc(fp): variable replacement
//bAddr: get address OR get value
//    1: get address
//    0: get value
//Address or value is returned in EAX
void emitRefer(SymbolRecord *s, int bAddr)
{
    switch(s->symboltype){
    // ARRAYADDR_SYMBOL represents for a array symbol
    // needs an indirected access(i.e. as parameter)
    case ARRAYADDR_SYMBOL:
        emitTwoOprand("MOV", regs[EAX],
            memAddr(BP, NONE, 0, s->location));
        emitTwoOprand(bAddr?"LEA":"MOV", regs[EAX],
            memAddr(EAX, EBX, Int_Bytes, 0));
        break;

    // Arrays that can be accessed directly
    case ARRAY_SYMBOL:
        // Global variables need a different way
        if(s->nestlevel == 0){
            emitTwoOprand(bAddr?"LEA":"MOV", regs[EAX],
                memAddr(NONE, EBX, Int_Bytes, "OFFSET _"+s->name));
        }
        else{
            emitTwoOprand(bAddr?"LEA":"MOV", regs[EAX],
                memAddr(EBP, EBX, Int_Bytes, s->location));
        }
        break;

    // Regular variables
    case VAR_SYMBOL:
        if(s->nestlevel == 0){
            emitTwoOprand(bAddr?"LEA":"MOV", regs[EAX],
                '_'+s->name);
        }
        else{
            emitTwoOprand(bAddr?"LEA":"MOV", regs[EAX],
                memAddr(BP, NONE, 0, s->location));
        }
        break;
    }
}
//
// Core code for code generation
//
// tempR: Register for temp result
//   0-6: R0-R6
//     8: On stack
//    -1: Abandon
void genCodePart(TreeNode *t,int tempR)
{
	TreeNode *ttemp;
    string label,label2;
	SymbolRecord *s;
    ostringstream os;
	int i;
	if (t != NULL)
	{
		switch(t->kind)
		{
		case DECLAR:
			if(t->childkind.declarK==FUNC_DEFINE)
			{
				//FuncName=t->name;
				s=st_lookup(t->name);
				emitComment(string("Function name: ")+t->name);
                emitLine('_'+t->name+" PROC");
                emitCode("PUSH BP");		//save the old-frame-pointer(ofp)
                emitCode("MOV BP,SP");		//set new fp
                if(s->localAlloc > 0){		//reserve for local variables
                    os<<s->localAlloc;
                    emitTwoOprand("SUB", regs[SP], os.str());
                    os.str()="";
                }
				st_addon(t->pBucketList);	//add on corresponding ST
                genCodePart(t->pChild[1], NONE);	//initialization part
				genCodePart(t->pChild[2], NONE);	//statement part
				st_takeoff();				//take it off
                emitCode("MOV SP,BP");
				emitCode("MOV EAX,0");		//return 0 by default
				emitCode("POP BP");			//fp=ofp
				emitNoOprand("RET");		//return
                emitLine('_'+t->name+" ENDP");
				//FuncName="";
				nestlevel=0;
			}
			// generate code for initialization
			else if(t->childkind.declarK==VAR_DECLAR_LIST) {
				ttemp = t->pChild[0];
				while(ttemp!=NULL) {
					genCodePart(ttemp->pChild[0], NONE);
					ttemp = ttemp->pNext;
				}
			}
			break;
		case CSTMT:
			emitComment("Compound statement start");
			st_addon(t->pBucketList);			//add on corresponding ST
			genCodePart(t->pChild[0], NONE);	//deal with possible initialization
			genCodePart(t->pChild[1], NONE);
			st_takeoff();			            //take it of
			emitComment("Compound statement end");
			break;
		case OP:
			genCodePart(t->pChild[0], STACK);   //oprand1 save to stack
			genCodePart(t->pChild[1], EBX);     //oprand2 save to EBX
			emitCode("POP EAX");                //get oprand1
			switch(t->tokenT)
			{
			case PLUS:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -