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

📄 codegen.cpp

📁 一个面向对像语言的编译器
💻 CPP
字号:
/* File: codegen.cc
 * ----------------
 * Implementation for the CodeGenerator class. The methods don't do anything
 * too fancy, mostly just create objects of the various Tac instruction
 * classes and append them to the list.
 */

#include "codegen.h"
#include "tac.h"
#include "declaration.h"
#include "type.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "decllist.h"
#include "taclist.h"
#include "typelist.h"
#include "hashtable.h"
#include "mips.h"
#include "scope.h"
#include "errors.h"
#include "ex86asm.h"

extern ScopeStack * scopes;
int myTop=-1;
int retTop=-1;

CodeGenerator::CodeGenerator()
{
  code = new TacList();
  topLocalOffset=OffsetToFirstLocal;
  topParaOffset=OffsetToFirstParam;
}

char *CodeGenerator::NewLabel()
{
  static int nextLabelNum = 0;
  char temp[8];
  sprintf(temp, "_L%d", nextLabelNum++);
  return strdup(temp);
}

Declaration *CodeGenerator::GenTempVar(Type *type)
{
  static int nextTempNum;
  char temp[12];
  sprintf(temp, "_tmp%d", nextTempNum++);
  Declaration *decl = new Declaration(Declaration::Variable, temp, type);
  decl->SetScope(scopes->GetCurrentScope());
  decl->SetOffset(topLocalOffset);
  topLocalOffset=topLocalOffset-VarSize;
  return decl;
}



Declaration *CodeGenerator::GenLoadConstant(int value, Type *type)
{
  Declaration *result = GenTempVar(type);
  code->Append(new LoadConstant(result, value));
  return result;
}

Declaration *CodeGenerator::GenLoadConstant(const char *s)
{
  Declaration *result = GenTempVar(Type::stringType);
  code->Append(new LoadStringConstant(result, s));
  return result;
} 

Declaration *CodeGenerator::GenLoadLabel(const char *label)
{
  Declaration *result = GenTempVar(Type::voidType);
  code->Append(new LoadLabel(result, label));
  return result;
} 


void CodeGenerator::GenAssign(Declaration *dst, Declaration *src)
{
  code->Append(new Assign(dst, src));
}


Declaration *CodeGenerator::GenLoad(Declaration *ref, Type *type, int offset)
{
  Declaration *result = GenTempVar(type);
  code->Append(new Load(result, ref, offset));
  return result;
}

void CodeGenerator::GenStore(Declaration *dst,Declaration *src, int offset)
{
  code->Append(new Store(dst, src, offset));
}


Declaration *CodeGenerator::GenBinaryOp(const char *opName, Declaration *op1,
						     Declaration *op2, Type *resultType)
{
  Declaration *result = GenTempVar(resultType);
  code->Append(new BinaryOp(Tac::OpCodeForName(opName), result, op1, op2));
  return result;
}


void CodeGenerator::GenLabel(const char *label,bool isfunlabel)
{
  Label * newLabel= new Label(label);
  newLabel->isFunLabel =isfunlabel;
  code->Append(newLabel);
}

void CodeGenerator::GenIfZ(Declaration *test, const char *label)
{
  code->Append(new IfZ(test, label));
}

void CodeGenerator::GenGoto(const char *label)
{
  code->Append(new Goto(label));
}

void CodeGenerator::GenReturn(Declaration *val)
{
  code->Append(new Return(val));
}


void CodeGenerator::GenBeginFunc(Declaration *fn)
{

  GenLabel(fn->GetFunctionLabel(),true);
  code->Append(new BeginFunc(fn));
}

void CodeGenerator::GenEndFunc(Declaration * fn)
{
  code->Append(new EndFunc(fn));
}

void CodeGenerator::GenPushParam(Declaration *param)
{
    code->Append(new PushParam(param));
}

Declaration *CodeGenerator::GenLCall(const char *label, int numParamBytes, Type *resultType)
{
  Declaration *result = resultType->IsEquivalentTo(Type::voidType)?
                         NULL : GenTempVar(resultType);
  code->Append(new LCall(label, numParamBytes, result));
  return result;
}

Declaration *CodeGenerator::GenACall(Declaration *fnAddr, int numParamBytes, Type *resultType)
{
  Declaration *result = resultType->IsEquivalentTo(Type::voidType)
                         ? NULL : GenTempVar(resultType);
  code->Append(new ACall(fnAddr, numParamBytes, result));
  return result;
}

 
 
static struct _builtin {
  const char *label;
  int numArgs;
} builtins[] =
 {{"_Alloc", 1},
  {"_ReadLine", 0},
  {"_ReadInteger", 0},
  {"_StringEqual", 2},
  {"_PrintInt", 1},
  {"_PrintString", 1},
  {"_PrintBool", 1},
  {"_Halt", 0}};

Declaration *CodeGenerator::GenBuiltInCall(BuiltIn bn, Type *returnType, Declaration *arg1, Declaration *arg2)
{
  Assert(bn >= 0 && bn < NumBuiltIns);
  struct _builtin *b = &builtins[bn];
  Declaration *result = NULL;

  if (returnType && !returnType->IsEquivalentTo(Type::voidType))
    result = GenTempVar(returnType);
                // verify appropriate number of non-NULL arguments given
  Assert((b->numArgs == 0 && !arg1 && !arg2)
	|| (b->numArgs == 1 && arg1 && !arg2)
	|| (b->numArgs == 2 && arg1 && arg2));
  if (arg2) code->Append(new PushParam(arg2));
  if (arg1) code->Append(new PushParam(arg1));
  code->Append(new LCall(b->label, VarSize*b->numArgs, result));
  return result;
}


void CodeGenerator::GenVTable(const char *className, DeclList *methods)
{
  code->Append(new VTable(className, methods));
}

void CodeGenerator::GenGVar(Declaration * decl)
{
  code->Append(new GVar(decl));
}

void CodeGenerator::Emit()
{
  if (IsDebugOn("tac")) 
  { // if debug don't translate to x86, just print Tac
	Tac::toWhat=Tac::ToNothing;
    for (int i = 0; i < code->NumElements(); i++)
	code->Nth(i)->Print();
   }  
  else  if (IsDebugOn("mips"))
  {
     Mips mips;
	 Tac::toWhat=Tac::ToMips;
     mips.EmitPreamble();
     for (int i = 0; i < code->NumElements(); i++)
	 code->Nth(i)->Emit(&mips);
  }
	else
  {
     Ex86asm x86;
	 Tac::toWhat=Tac::ToX86;
     x86.EmitPreamble();
     for (int i = 0; i < code->NumElements(); i++)
	 code->Nth(i)->Emit(&x86);
	 printf("\nEND _@main\n");

  }
}

/////////////////////////////////////////////////////////
/*新添加函数的实现*/
/////////////////////////////////////////////////////////

void CodeGenerator::PushLabel(char *label)
{
	myTop++;
	labelStack[myTop]=label;
}

void CodeGenerator::PopLabel(int count)
{
	myTop=myTop-count;
}

char * CodeGenerator::GetLabel(int index)
{
	return labelStack[myTop-index];
}

void CodeGenerator::InitLocalOffset()
{
	topLocalOffset=OffsetToFirstLocal;
}

void CodeGenerator::SetLocalOffset(Declaration *decl)
{
	decl->SetOffset(topLocalOffset);
	topLocalOffset=topLocalOffset-VarSize;
}

void CodeGenerator::InitParaOffset()
{
	topParaOffset=OffsetToFirstParam;
}

void CodeGenerator::SetParaOffset(Declaration *decl)
{
	decl->SetOffset(topParaOffset);
	topParaOffset=topParaOffset+VarSize;
}



int CodeGenerator::GetStackFrameSize(StackSize temp)
{
	switch(temp) {
	case LocalStackSize:
		return OffsetToFirstLocal-topLocalOffset;
		break;
	case ParaStackSize:
		return topParaOffset-OffsetToFirstParam+4;
		break;
	case ClassStackSize:
		return topIvarOffset-OffsetToFirstIvar+4;
	default:
		return 0;
	}
}

void CodeGenerator::InitIVarOffset()
{
	topIvarOffset=OffsetToFirstIvar;
}

void CodeGenerator::InitMethodOffset()
{
	topMethodOffset=OffsetToFirstMethod;
}

void CodeGenerator::SetIVarOffset(Declaration *decl)
{
	decl->SetOffset(topIvarOffset);
	topIvarOffset=topIvarOffset+VarSize;
}

void CodeGenerator::SetMethodOffset(Declaration *decl)
{
	decl->SetOffset(topMethodOffset);
	topMethodOffset=topMethodOffset+VarSize;
}

char * CodeGenerator::GetTopLabel()
{
	return labelStack[myTop];
}

void CodeGenerator::SetTopMethodOffset(int offset)
{
	topMethodOffset=offset;
}

void CodeGenerator::SetTopIVarOffset(int offset)
{
	topIvarOffset=offset;
}

void CodeGenerator::PushRetLabel(char *retLabel)
{
	retTop++;
	retLabelStack[retTop]=retLabel;
}

void CodeGenerator::PopRetLabel(int count)
{
	retTop=retTop-count;
}

char * CodeGenerator::GetRetLabel(int index)
{
	return retLabelStack[index];
}

char * CodeGenerator::GetRetTopLabel()
{
	return retLabelStack[retTop];
}

⌨️ 快捷键说明

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