From afcfcec2a76deac3e43bc1f64741a679877b8512 Mon Sep 17 00:00:00 2001 From: rechardchen Date: Wed, 17 May 2017 16:06:11 +0800 Subject: [PATCH] to begin MC research x86 ISA --- absyn.h | 4 +- semant.cpp | 202 +++++++++++++++++++++++++++++++++++++++++--------- semant.h | 4 +- symbol.h | 3 + tiger.g4 | 1 + translate.cpp | 88 +++++++++++++++++++--- translate.h | 5 +- 7 files changed, 261 insertions(+), 46 deletions(-) diff --git a/absyn.h b/absyn.h index cefe6a2..e9dbcdd 100644 --- a/absyn.h +++ b/absyn.h @@ -167,14 +167,14 @@ namespace tiger VarDec() :BaseASTNode(A_VarDec) {} std::string name, type; ASTNode init=nullptr; - bool escape = false; + bool escape = true; }; struct Field : public BaseASTNode { Field() : BaseASTNode(A_Field) {} std::string name; std::string type; - bool escape = false; + bool escape = true; }; struct TyFields : public BaseASTNode { diff --git a/semant.cpp b/semant.cpp index ce83067..228f06f 100644 --- a/semant.cpp +++ b/semant.cpp @@ -2,6 +2,8 @@ #include "type.h" #include "translate.h" +//TODO: +//error recovery policy:1. add position info in reportErr 2.report error like gcc namespace tiger { #define VALID_VAR_TYPE(ty) ((ty)->tt != Ty_Void) @@ -14,8 +16,8 @@ namespace tiger { { Translator = new (C) Translate(C); } - - Semant::ExpTy Semant::TransExp(ASTNode n) + + Semant::ExpTy Semant::TransExp(ASTNode n,Label loopExit) { ExpTy ret; switch (n->type) { @@ -47,7 +49,7 @@ namespace tiger { auto ax = static_cast(n); auto ty = TENV.Look(ax->type); if (ty) { - auto expty = TransExp(ax->init); + auto expty = TransExp(ax->init); //break can not in array init exp if (expty.second == nullptr) goto TRANS_EXP_ERR; if (!ValidateTypeCheck(ty, expty.second)) { @@ -55,7 +57,7 @@ namespace tiger { goto TRANS_EXP_ERR; } auto initExp = expty.first; - expty = TransExp(ax->size); + expty = TransExp(ax->size); //break can not in array size exp if (expty.second == nullptr) goto TRANS_EXP_ERR; if (expty.second != IntType()) { @@ -336,9 +338,9 @@ namespace tiger { case A_If: { auto ix = static_cast(n); - ExpTy test = TransExp(ix->test), then = TransExp(ix->then), elsee; + ExpTy test = TransExp(ix->test), then = TransExp(ix->then, loopExit), elsee;//breakexp can in then bool hasElse = ix->elsee != nullptr; - if (hasElse) elsee = TransExp(ix->elsee); + if (hasElse) elsee = TransExp(ix->elsee, loopExit); if (test.second == nullptr) goto TRANS_EXP_ERR; if (!VALID_VAR_TYPE(test.second)) { @@ -373,21 +375,129 @@ namespace tiger { case A_While: { + auto wx = static_cast(n); + + Label end = temp::newLabel(); //TODO: refactor + ExpTy test = TransExp(wx->test), body = TransExp(wx->body, end); + if (test.second == nullptr || body.second == nullptr) + goto TRANS_EXP_ERR; + if (!VALID_VAR_TYPE(test.second)) { + reportErr("test oprand type invalid"); + goto TRANS_EXP_ERR; + } + ret.second = VoidType(); + ret.first = Translator->TransWhile(test.first, body.first, end); } break; case A_For: { + auto fx = static_cast(n); + + auto low = TransExp(fx->lo), high = TransExp(fx->hi); + if (low.second == nullptr || high.second == nullptr) + goto TRANS_EXP_ERR; + if (low.second != IntType() || high.second != IntType()) { + if (low.second != IntType()) + reportErr("invalid oprand type!"); + if (high.second != IntType()) + reportErr("invalid oprand type!"); + goto TRANS_EXP_ERR; + } + VENV.BeginScope(); + auto ventry = new(C)VarEntry; + ventry->access = Translator->CurLevel()->AllocLocal(true); //TODO: escape analysis + ventry->type = IntType(); + VENV.Enter(fx->var, ventry); + + Label end = temp::newLabel(); + auto body = TransExp(fx->body, end); + if (body.second == nullptr) { + VENV.EndScope(); + goto TRANS_EXP_ERR; + } + + ret.second = VoidType(); + ret.first = Translator->TransFor(ventry->access, low.first, + high.first, body.first, end); + VENV.EndScope(); } break; case A_Break: + { + if (!loopExit) { + reportErr("break exp not in a loop!"); + goto TRANS_EXP_ERR; + } + + ret.second = VoidType(); + ret.first = Translator->TransBreak(loopExit); + } break; case A_Let: + { + auto lx = static_cast(n); + + VENV.BeginScope(); + TENV.BeginScope(); + FENV.BeginScope(); + + auto decs = TransDecs(lx->decs), body = TransExp(lx->exps, loopExit); + if (decs.second == nullptr || body.second == nullptr) { + FENV.EndScope(); + TENV.EndScope(); + VENV.EndScope(); + goto TRANS_EXP_ERR; + } + + ret.second = body.second; + ret.first = Translator->CombineESeq(decs.first, body.first); + FENV.EndScope(); + TENV.EndScope(); + VENV.EndScope(); + } + break; + + case A_ExpList: + { + auto ex = static_cast(n); + Type*ty = VoidType(); + for (auto exp : ex->exps) { + auto expty = TransExp(exp, loopExit); + if (expty.second == nullptr) ty = nullptr; + else ty = expty.second; + + exps + } + if (ty != nullptr) { + ret.second = ty; + ret.first = nullptr; + + } + } + break; + + case A_Assign: + { + auto ax = static_cast(n); + auto var = TransVar(ax->var); + auto exp = TransExp(ax->exp); + if (var.second == nullptr || exp.second == nullptr) { + goto TRANS_EXP_ERR; + } + if (!ValidateTypeCheck(var.second, exp.second)) { + reportErr("type mismatch!"); + goto TRANS_EXP_ERR; + } + ret.second = VoidType(); + ret.first = Translator->TransAssign(var.first, exp.first); + } break; + default: assert(0); break; @@ -399,10 +509,11 @@ namespace tiger { Semant::ExpTy Semant::TransDecs(ASTNode n) { - //TODO: handle class definitions + //TODO: object-oriented features assert(n->type == A_DeclareList); DeclareList* dl = static_cast(n); TrExp* initExp = nullptr; + Type* decType = VoidType(); //first pass only process type headers for (auto dec : dl->decs) { @@ -428,31 +539,45 @@ namespace tiger { auto ty = TENV.Look(typeName); assert(ty->tt == Ty_Name); auto nt = static_cast(ty); - nt->type = TransTy(tydec); - - //check: recursive define and incomplete define - Type* realTy = nt->type; - while (realTy != nt && realTy->tt == Ty_Name) { - auto realNT = static_cast(realTy); - if (realNT->type == nullptr) { - reportErr("type %s has an incomplete definition!", tydec->name.c_str()); - //TODO: pop error type - break; + auto type = TransTy(tydec); + if (type) { + nt->type = type; + //check: recursive define and incomplete define + Type* realTy = nt->type; + while (realTy != nt && realTy->tt == Ty_Name) { + auto realNT = static_cast(realTy); + if (realNT->type == nullptr) { + reportErr("type %s has an incomplete definition!", tydec->name.c_str()); + TENV.Pop(typeName); + decType = nullptr; + break; + } + else + realTy = realNT->type; + } + if (realTy == nt) { + reportErr("type %s has a recursive definition!", tydec->name.c_str()); + TENV.Pop(typeName); + decType = nullptr; } - else - realTy = realNT->type; } - if (realTy == nt) - reportErr("type %s has a recursive definition!", tydec->name.c_str()); } - else if (dec->type == A_VarDec) { + } + + //when type info process finished,process var dec and func decs + for (auto dec : dl->decs) { + if (dec->type == A_VarDec) { auto vardec = static_cast(dec); auto expty = TransVarDec(vardec); if (expty.second) { - if (initExp == nullptr) + /*if (initExp == nullptr) initExp = expty.first; - else - initExp = Translator->CombineStm(initExp, expty.first); + else + initExp = Translator->CombineStm(initExp, expty.first);*/ + initExp = Translator->CombineStm(initExp, expty.first); + } + else { + decType = nullptr; } } else if (dec->type == A_FuncDec) { @@ -474,9 +599,9 @@ namespace tiger { std::vector formalTypes; std::vector formalEscape; for (auto para : fundec->params->fields) { - Type* ty = TENV.Look(para->name); + Type* ty = TENV.Look(para->type); if (!ty) { - reportErr("para %s has invalid type %s", para->name.c_str(), + reportErr("param %s has invalid type %s", para->name.c_str(), para->type.c_str()); validParam = false; break; @@ -504,7 +629,7 @@ namespace tiger { TENV.BeginScope(); VENV.BeginScope(); FENV.BeginScope(); - + for (size_t i = 0; i < formalName.size(); ++i) { auto entry = new(C)VarEntry; entry->access = newLevel->Argument(i); @@ -518,20 +643,29 @@ namespace tiger { VENV.EndScope(); TENV.EndScope(); //check return type - if (expty.second == NULL || - !ValidateTypeCheck(retType, expty.second)) { - reportErr("return type mismatch!"); + if (expty.second == nullptr) { FENV.Pop(fundec->name); Translator->ExitLevel(nullptr); } else { - Translator->ExitLevel(expty.first); + if (!ValidateTypeCheck(retType, expty.second)) { + reportErr("return type mismatch!"); + FENV.Pop(fundec->name); + Translator->ExitLevel(nullptr); + decType = nullptr; + } + else { + Translator->ExitLevel(expty.first); + } } } + else { + decType = nullptr; + } } } - return ExpTy(initExp, nullptr); + return ExpTy(initExp, decType); } Semant::ExpTy Semant::TransVar(ASTNode n) @@ -691,6 +825,8 @@ namespace tiger { } Semant::ExpTy Semant::TransVarDec(VarDec* vardec) { + //TODO: can not handle following recursive format + //var a := recType{ptr=a} Type* ty = nullptr; TrExp* exp = nullptr; ExpTy ret(nullptr, nullptr); diff --git a/semant.h b/semant.h index 85f6ce3..ef4467a 100644 --- a/semant.h +++ b/semant.h @@ -3,6 +3,7 @@ #include "env.h" #include "absyn.h" #include "allocator.h" +#include "temp.h" #include namespace tiger { @@ -20,7 +21,8 @@ namespace tiger { Semant(BumpPtrAllocator& allocator); //make sure if ExpTy returned is successful, then ty is actual typed - ExpTy TransExp(ASTNode); //expty.second null if trans failed, else is actualed type + //loopExit is the outer loop to break + ExpTy TransExp(ASTNode,Label=""); //expty.second null if trans failed, else is actualed type ExpTy TransDecs(ASTNode);//Declaration list ExpTy TransVar(ASTNode); Type* TransTy(ASTNode); diff --git a/symbol.h b/symbol.h index df226af..cf76715 100644 --- a/symbol.h +++ b/symbol.h @@ -28,6 +28,9 @@ namespace tiger inline operator std::string() const { return mName ? std::string(mName) : std::string(""); } + inline operator bool() const { + return mName != nullptr; + } public: struct Hasher { diff --git a/tiger.g4 b/tiger.g4 index b92db93..e2bcfc3 100644 --- a/tiger.g4 +++ b/tiger.g4 @@ -36,6 +36,7 @@ exp | 'let' decs 'in' exps 'end' #LetExp ; +// Can not handle lvalue such as F(x,y), todo add this lvalue : ID #SimpleVar | lvalue '.' ID #FieldVar diff --git a/translate.cpp b/translate.cpp index 214b141..89aaf72 100644 --- a/translate.cpp +++ b/translate.cpp @@ -256,13 +256,40 @@ namespace tiger { TrExp* Translate::CombineStm(TrExp* s1, TrExp* s2) { - assert(s1 != nullptr && s2 != nullptr); - return new(C)TrNx( - new(C)TSeq( - s1->unNx(), - s2->unNx() - ), C - ); + if (s1 == nullptr && s2 == nullptr) { + return nullptr; + } + else if (s1 == nullptr) { + return s2; + } + else if (s2 == nullptr) { + return s1; + } + else { + return new(C)TrNx(new(C)TSeq(s1->unNx(), s2->unNx()),C); + } + } + + TrExp* Translate::CombineESeq(TrExp* s, TrExp* e) + { + if (s == nullptr && e == nullptr) { + return new(C)TrEx(new(C)TConst(0),C); + } + else if (s == nullptr) { + return e; + } + else if (e == nullptr) { + return new(C)TrEx(new(C)TEseq( + s->unNx(), + new(C)TConst(0) + ), C); + } + else { + return new(C)TrEx(new(C)TEseq( + s->unNx(), + e->unEx() + ), C); + } } TrExp* Translate::TransSimpleVar(TrAccess vAccess) @@ -396,6 +423,7 @@ namespace tiger { TrExp* Translate::TransCall(Label f, const std::vector& exps) { + //TODO: set static link std::vector params; for (auto e : exps) params.push_back(e->unEx()); return new(C)TrEx(new(C)TCall( @@ -496,9 +524,51 @@ namespace tiger { return new(C)TrIf(test, then, elsee, C); } - /*TrExp* Translate::TransFor(TrExp* lo, TrExp* hi, TrExp* body) + TrExp* Translate::TransWhile(TrExp* test, TrExp* body, Label end) { + auto begin = temp::newLabel(); + auto tlabel = temp::newLabel(); + return new(C)TrNx( + new(C)TSeq( + new(C)TLabel(begin), + new(C)TSeq( + test->unCx(tlabel,end), + new(C)TSeq( + new(C)TLabel(tlabel), + new(C)TSeq( + body->unNx(), + new(C)TSeq( + new(C)TJump(begin, { begin }), + new(C)TLabel(end) + ) + ) + ) + ) + ), C + ); + } + TrExp* Translate::TransBreak(Label loopExit) + { + return new(C)TrNx(new(C)TJump(loopExit, { loopExit }), C); + } + + TrExp* Translate::TransFor(TrAccess i, TrExp* lo, TrExp* hi, TrExp* body, Label end) + { + auto counter = TransSimpleVar(i); + auto hiReg = temp::newTemp(); + auto init = new(C)TSeq( + new(C)TMove(counter->unEx(), lo->unEx()), + new(C)TMove(new(C)TTemp(hiReg), hi->unEx()) + ); + auto test = TransRelOp(Tr_LE, counter, + new(C)TrEx(new(C)TTemp(hiReg), C)); + auto forbody = CombineStm(body, + new(C)TrNx( + new(C)TMove(counter->unEx(), + new(C)TBinOp(T_plus, counter->unEx(), new(C)TConst(1)) + ),C)); + return CombineStm(new(C)TrNx(init, C), + TransWhile(test, forbody, end)); } -*/ } \ No newline at end of file diff --git a/translate.h b/translate.h index 7cda41c..48f5e82 100644 --- a/translate.h +++ b/translate.h @@ -54,6 +54,7 @@ namespace tiger { void ExitLevel(TrExp* body); TrExp* CombineStm(TrExp* s1, TrExp* s2); + TrExp* CombineESeq(TrExp* s, TrExp* e); TrExp* TransSimpleVar(TrAccess); TrExp* TransFieldVar(TrExp* var, RecordType* type, Symbol field); @@ -73,7 +74,9 @@ namespace tiger { TrExp* TransRelOp(TrRelOp op, TrExp* lhs, TrExp* rhs, bool strOprand=false); TrExp* TransLogicOp(TrLogicOp op, TrExp* lhs, TrExp* rhs); TrExp* TransIf(TrExp* test, TrExp* then, TrExp* elsee); - TrExp* TransFor(TrExp* lo, TrExp* hi, TrExp* body); + TrExp* TransWhile(TrExp* test, TrExp* body, Label end); + TrExp* TransFor(TrAccess i, TrExp* lo, TrExp* hi, TrExp* body, Label end); + TrExp* TransBreak(Label); private: TrLevel* InitLevel, *CurrentLevel;