Example #1
0
        private static void CgAssignStat(FuncInfo fi, AssignStat node)
        {
            var exps  = RemoveTailNil(node.ExpList);
            var nExps = exps.Count;
            var nVars = node.VarList.Count;

            var tRegs   = new int[nVars];
            var kRegs   = new int[nVars];
            var vRegs   = new int[nVars];
            var oldRegs = fi.UsedRegs;

            for (var i = 0; i < node.VarList.Count; i++)
            {
                var exp = node.VarList[i];

                if (exp is TableAccessExp tableAccessExp)
                {
                    tRegs[i] = fi.AllocReg();
                    CgExp(fi, tableAccessExp.PrefixExp, tRegs[i], 1);
                    kRegs[i] = fi.AllocReg();
                    CgExp(fi, tableAccessExp.KeyExp, kRegs[i], 1);
                }
                else if (exp is NameExp nameExp)
                {
                    var name = nameExp.Name;

                    if (fi.SlotOfLocVar(name) < 0 && fi.IndexOfUpval(name) < 0)
                    {
                        kRegs[i] = -1;
                        fi.IndexOfConstant(name, out var constIdx);
                        if (constIdx > 0xff)
                        {
                            kRegs[i] = fi.AllocReg();
                        }
                    }
                }
            }

            for (var i = 0; i < nVars; i++)
            {
                vRegs[i] = fi.UsedRegs + i;
            }

            if (nExps >= nVars)
            {
                for (var i = 0; i < exps.Count; i++)
                {
                    var exp = exps[i];
                    var a   = fi.AllocReg();
                    if (i >= nVars && i == nExps - 1 && IsVarargOrFuncCall(exp))
                    {
                        CgExp(fi, exp, a, 0);
                    }
                    else
                    {
                        CgExp(fi, exp, a, 1);
                    }
                }
            }
            else
            {
                var multRet = false;

                for (var i = 0; i < exps.Count; i++)
                {
                    var exp = exps[i];
                    var a   = fi.AllocReg();
                    if (i == nExps - 1 && IsVarargOrFuncCall(exp))
                    {
                        multRet = true;
                        var n = nVars - nExps + 1;
                        CgExp(fi, exp, a, n);
                        fi.AllocRegs(n - 1);
                    }
                    else
                    {
                        CgExp(fi, exp, a, 1);
                    }
                }

                if (!multRet)
                {
                    var n = nVars - nExps;
                    var a = fi.AllocRegs(n);
                    fi.EmitLoadNil(a, n);
                }
            }

            for (var i = 0; i < node.VarList.Count; i++)
            {
                var exp = node.VarList[i];

                if (exp is NameExp nameExp)
                {
                    var varName = nameExp.Name;
                    var a       = fi.SlotOfLocVar(varName);

                    if (a >= 0)
                    {
                        fi.EmitMove(a, vRegs[i]);
                    }
                    else
                    {
                        var b = fi.IndexOfUpval(varName);
                        if (b >= 0)
                        {
                            fi.EmitSetUpval(vRegs[i], b);
                        }
                        else
                        {
                            a = fi.SlotOfLocVar("_ENV");
                            if (a >= 0)
                            {
                                if (kRegs[i] < 0)
                                {
                                    fi.IndexOfConstant(varName, out var constIdx);
                                    b = 0x100 + constIdx;
                                    fi.EmitSetTable(a, b, vRegs[i]);
                                }
                                else
                                {
                                    fi.EmitSetTable(a, kRegs[i], vRegs[i]);
                                }
                            }
                            else
                            {
                                a = fi.IndexOfUpval("_ENV");
                                if (kRegs[i] < 0)
                                {
                                    fi.IndexOfConstant(varName, out var idx);
                                    b = 0x100 + idx;
                                    fi.EmitSetTabUp(a, b, vRegs[i]);
                                }
                                else
                                {
                                    fi.EmitSetTable(a, kRegs[i], vRegs[i]);
                                }
                            }
                        }
                    }
                }
                else
                {
                    fi.EmitSetTable(tRegs[i], kRegs[i], vRegs[i]);
                }
            }

            fi.UsedRegs = oldRegs;
        }
Example #2
0
        private static void CgExp(FuncInfo fi, Exp node, int a, int n)
        {
            switch (node)
            {
            case NilExp _:
                fi.EmitLoadNil(a, n);
                break;

            case FalseExp _:
                fi.EmitLoadBool(a, 0, 0);
                break;

            case TrueExp _:
                fi.EmitLoadBool(a, 1, 0);
                break;

            case IntegerExp integerExp:
                fi.EmitLoadK(a, integerExp.Val);
                break;

            case FloatExp floatExp:
                fi.EmitLoadK(a, floatExp.Val);
                break;

            case StringExp stringExp:
                fi.EmitLoadK(a, stringExp.Str);
                break;

            case ParensExp parensExp:
                CgExp(fi, parensExp.Exp, a, 1);
                break;

            case VarargExp varargExp:
                CgVarargExp(fi, varargExp, a, n);
                break;

            case FuncDefExp funcDefExp:
                CgFuncDefExp(fi, funcDefExp, a);
                break;

            case TableConstructorExp tableConstructorExp:
                CgTableConstructorExp(fi, tableConstructorExp, a);
                break;

            case UnopExp unopExp:
                CgUnopExp(fi, unopExp, a);
                break;

            case BinopExp binopExp:
                CgBinopExp(fi, binopExp, a);
                break;

            case ConcatExp concatExp:
                CgConcatExp(fi, concatExp, a);
                break;

            case NameExp nameExp:
                CgNameExp(fi, nameExp, a);
                break;

            case TableAccessExp tableAccessExp:
                CgTableAccessExp(fi, tableAccessExp, a);
                break;

            case FuncCallExp funcCallExp:
                CgFuncCallExp(fi, funcCallExp, a, n);
                break;
            }
        }
Example #3
0
        private static void CgLocalVarDeclStat(FuncInfo fi, LocalVarDeclStat node)
        {
            var exps    = RemoveTailNil(node.ExpList);
            var nExps   = exps.Count;
            var nNames  = node.NameList.Count;
            var oldRegs = fi.UsedRegs;

            if (nExps == nNames)
            {
                foreach (var exp in exps)
                {
                    var a = fi.AllocReg();
                    CgExp(fi, exp, a, 1);
                }
            }
            else if (nExps > nNames)
            {
                for (var i = 0; i < exps.Count; i++)
                {
                    var exp = exps[i];
                    var a   = fi.AllocReg();
                    if (i == nExps - 1 && IsVarargOrFuncCall(exp))
                    {
                        CgExp(fi, exp, a, 0);
                    }
                    else
                    {
                        CgExp(fi, exp, a, 1);
                    }
                }
            }
            else
            {
                var multRet = false;
                for (var i = 0; i < exps.Count; i++)
                {
                    var exp = exps[i];
                    var a   = fi.AllocReg();
                    if (i == nExps - 1 && IsVarargOrFuncCall(exp))
                    {
                        multRet = true;
                        var n = nNames - nExps + 1;
                        CgExp(fi, exp, a, n);
                        fi.AllocRegs(n - 1);
                    }
                    else
                    {
                        CgExp(fi, exp, a, 1);
                    }
                }

                if (!multRet)
                {
                    var n = nNames - nExps;
                    var a = fi.AllocRegs(n);
                    fi.EmitLoadNil(a, n);
                }
            }

            fi.UsedRegs = oldRegs;
            foreach (var name in node.NameList)
            {
                fi.AddLocVar(name);
            }
        }