Пример #1
0
        private static void CgTableConstructorExp(FuncInfo fi, TableConstructorExp node, int a)
        {
            var nArr    = node.KeyExps?.Count(exp => exp is null) ?? 0;
            var nExps   = node.KeyExps?.Count ?? 0;
            var multRet = nExps > 0 && IsVarargOrFuncCall(node.ValExps[nExps - 1]);

            fi.EmitNewTable(a, nArr, nExps - nArr);
            var arrIdx = 0;

            for (var i = 0; i < nExps; i++)
            {
                var keyExp = node.KeyExps[i];
                var valExp = node.ValExps[i];

                if (keyExp == null)
                {
                    arrIdx++;
                    var tmp = fi.AllocReg();
                    if (i == nExps - 1 && multRet)
                    {
                        CgExp(fi, valExp, tmp, -1);
                    }
                    else
                    {
                        CgExp(fi, valExp, tmp, 1);
                    }

                    if (arrIdx % 50 == 0 || arrIdx == nArr)
                    {
                        var n = arrIdx % 50;
                        if (n == 0)
                        {
                            n = 50;
                        }

                        fi.FreeRegs(n);
                        var c = (arrIdx - 1) / 50 + 1;
                        if (i == nExps - 1 && multRet)
                        {
                            fi.EmitSetList(a, 0, c);
                        }
                        else
                        {
                            fi.EmitSetList(a, n, c);
                        }
                    }

                    continue;
                }

                var b = fi.AllocReg();
                CgExp(fi, keyExp, b, 1);
                var d = fi.AllocReg();
                CgExp(fi, valExp, d, 1);
                fi.FreeRegs(2);
                fi.EmitSetTable(a, b, d);
            }
        }
Пример #2
0
        private static void CgTableAccessExp(FuncInfo fi, TableAccessExp node, int a)
        {
            var b = fi.AllocReg();

            CgExp(fi, node.PrefixExp, b, 1);
            var c = fi.AllocReg();

            CgExp(fi, node.KeyExp, c, 1);
            fi.EmitGetTable(a, b, c);
            fi.FreeRegs(2);
        }
Пример #3
0
        private static void CgConcatExp(FuncInfo fi, ConcatExp node, int a)
        {
            foreach (var subExp in node.Exps)
            {
                var tmp = fi.AllocReg();
                CgExp(fi, subExp, tmp, 1);
            }

            var c = fi.UsedRegs - 1;
            var b = c - node.Exps.Count + 1;

            fi.FreeRegs(c - b + 1);
            fi.EmitABC(EOpCode.OP_CONCAT, a, b, c);
        }
Пример #4
0
        private static int PrepFuncCall(FuncInfo fi, FuncCallExp node, int a)
        {
            var nArgs = node.Args?.Count ?? 0;
            var lastArgIsVarargsOrFuncCall = false;

            CgExp(fi, node.PrefixExp, a, 1);
            if (node.NameExp != null)
            {
                fi.IndexOfConstant(node.NameExp.Str, out var idx);
                var c = 0x100 + idx;
                fi.EmitSelf(a, a, c);
            }

            for (var i = 0; i < nArgs; i++)
            {
                var arg = node.Args[i];
                var tmp = fi.AllocReg();
                if (i == nArgs - 1 && IsVarargOrFuncCall(arg))
                {
                    lastArgIsVarargsOrFuncCall = true;
                    CgExp(fi, arg, tmp, -1);
                }
                else
                {
                    CgExp(fi, arg, tmp, 1);
                }
            }

            fi.FreeRegs(nArgs);

            if (node.NameExp != null)
            {
                nArgs++;
            }

            if (lastArgIsVarargsOrFuncCall)
            {
                nArgs = -1;
            }

            return(nArgs);
        }
Пример #5
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;
            }
            }
        }
Пример #6
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);
            }
        }