📄 codegen.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 + -