Esempio n. 1
0
        private static void CgFuncCallStat(FuncInfo fi, FuncCallStat node)
        {
            var r = fi.AllocReg();

            CgFuncCallExp(fi, node, r, 0);
            fi.FreeReg();
        }
Esempio n. 2
0
        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();
        }
Esempio n. 3
0
        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;
            }
            }
        }
Esempio n. 4
0
        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();
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
            }
        }
Esempio n. 7
0
        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);
            }
        }