private static void CgFuncCallStat(FuncInfo fi, FuncCallStat node) { var r = fi.AllocReg(); CgFuncCallExp(fi, node, r, 0); fi.FreeReg(); }
private static void CgUnopExp(FuncInfo fi, UnopExp node, int a) { var b = fi.AllocReg(); CgExp(fi, node.Exp, b, 1); fi.EmitUnaryOp(node.GetOpCode(), a, b); fi.FreeReg(); }
private static void CgBinopExp(FuncInfo fi, BinopExp node, int a) { switch (node.Op) { case ETokenType.OpAnd: case ETokenType.OpOr: { var b = fi.AllocReg(); CgExp(fi, node.Exp1, b, 1); fi.FreeReg(); if (node.Op == ETokenType.OpAnd) { fi.EmitTestSet(a, b, 0); } else { fi.EmitTestSet(a, b, 1); } var pcOfJmp = fi.EmitJmp(0, 0); b = fi.AllocReg(); CgExp(fi, node.Exp2, b, 1); fi.FreeReg(); fi.EmitMove(a, b); fi.FixsBx(pcOfJmp, fi.PC() - pcOfJmp); break; } default: { var b = fi.AllocReg(); CgExp(fi, node.Exp1, b, 1); var c = fi.AllocReg(); CgExp(fi, node.Exp2, c, 1); fi.EmitBinaryOp(node.Op, a, b, c); fi.FreeRegs(2); break; } } }
private static void CgRepeatStat(FuncInfo fi, RepeatStat node) { fi.EnterScope(true); var pcBeforeBlock = fi.PC(); CgBlock(fi, node.Block); var r = fi.AllocReg(); CgExp(fi, node.Exp, r, 1); fi.FreeReg(); fi.EmitTest(r, 0); fi.EmitJmp(fi.GetJmpArgA(), pcBeforeBlock - fi.PC() - 1); fi.CloseOpenUpvals(); fi.ExitScope(); }
private static void CgWhileStat(FuncInfo fi, WhileStat node) { var pcBeforeExp = fi.PC(); var r = fi.AllocReg(); CgExp(fi, node.Exp, r, 1); fi.FreeReg(); fi.EmitTest(r, 0); var pcJmpToEnd = fi.EmitJmp(0, 0); fi.EnterScope(true); CgBlock(fi, node.Block); fi.CloseOpenUpvals(); fi.EmitJmp(0, pcBeforeExp - fi.PC() - 1); fi.ExitScope(); fi.FixsBx(pcJmpToEnd, fi.PC() - pcJmpToEnd); }
private static void CgIfStat(FuncInfo fi, IfStat node) { var pcJmpToEnds = new int[node.Exps.Count]; var pcJmpToNextExp = -1; for (var i = 0; i < node.Exps.Count; i++) { var exp = node.Exps[i]; if (pcJmpToNextExp >= 0) { fi.FixsBx(pcJmpToNextExp, fi.PC() - pcJmpToNextExp); } var r = fi.AllocReg(); CgExp(fi, exp, r, 1); fi.FreeReg(); fi.EmitTest(r, 0); pcJmpToNextExp = fi.EmitJmp(0, 0); fi.EnterScope(false); CgBlock(fi, node.Blocks[i]); fi.CloseOpenUpvals(); fi.ExitScope(); if (i < node.Exps.Count - 1) { pcJmpToEnds[i] = fi.EmitJmp(0, 0); } else { pcJmpToEnds[i] = pcJmpToNextExp; } } foreach (var pc in pcJmpToEnds) { fi.FixsBx(pc, fi.PC() - pc); } }
private static void CgRetStat(FuncInfo fi, List <Exp> exps) { var nExps = exps.Count; if (nExps == 0) { fi.EmitReturn(0, 0); return; } if (nExps == 1) { if (exps[0] is NameExp nameExp) { var r = fi.SlotOfLocVar(nameExp.Name); if (r >= 0) { fi.EmitReturn(r, 1); return; } } if (exps[0] is FuncCallExp fcExp) { var r = fi.AllocReg(); CgTailCallExp(fi, fcExp, r); fi.FreeReg(); fi.EmitReturn(r, -1); return; } } var multRet = IsVarargOrFuncCall(exps[nExps - 1]); for (var i = 0; i < nExps; i++) { var exp = exps[i]; var r = fi.AllocReg(); if (i == nExps - 1 && multRet) { CgExp(fi, exp, r, -1); } else { CgExp(fi, exp, r, 1); } } fi.FreeRegs(nExps); var a = fi.UsedRegs; if (multRet) { fi.EmitReturn(a, -1); } else { fi.EmitReturn(a, nExps); } }