Ejemplo n.º 1
0
        private void Return()
        {
            var node = Node.As <CallNode>();
            var decl = node.FunctionDeclaration;

            int i;
            var rets = node.Return;

            for (i = 0; i < 2; i++)
            {
                var ret = decl.GetReturn(i);
                var op  = rets[i];

                if (op.IsInvalid() || ret.RegisterIndex == RegisterIndex.Invalid || !op.IsVariable())
                {
                    continue;
                }

                var vd       = Compiler.GetVariableData(op.Id);
                var vf       = vd.Type.GetVariableInfo().ValueFlags;
                var regIndex = ret.RegisterIndex;

                switch (vd.Info.RegisterClass)
                {
                case RegisterClass.Gp:
                    if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass)
                    {
                        throw new ArgumentException();
                    }

                    Translator.Unuse(vd, RegisterClass.Gp);
                    Translator.Attach(vd, RegisterClass.Gp, regIndex, true);
                    break;

                case RegisterClass.Mm:
                    if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass)
                    {
                        throw new ArgumentException();
                    }

                    Translator.Unuse(vd, RegisterClass.Mm);
                    Translator.Attach(vd, RegisterClass.Mm, regIndex, true);
                    break;

                case RegisterClass.Xyz:
                    if (ret.VariableType == VariableType.Fp32 || ret.VariableType == VariableType.Fp64)
                    {
                        var m = new Memory(Translator.GetVarMem(vd), (vf & VariableValueFlags.Sp) != 0 ? 4 : (vf & VariableValueFlags.Dp) != 0 ? 8 : ret.VariableType == VariableType.Fp32 ? 4 : 8);
                        Translator.Unuse(vd, RegisterClass.Xyz, VariableUsage.Mem);
                        CodeContext.Fstp(m);
                    }
                    else
                    {
                        if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass)
                        {
                            throw new ArgumentException();
                        }

                        Translator.Unuse(vd, RegisterClass.Xyz);
                        Translator.Attach(vd, RegisterClass.Xyz, regIndex, true);
                    }
                    break;
                }
            }
        }
Ejemplo n.º 2
0
        private void Alloc(RegisterClass @class)
        {
            if (Done.Get(@class) == Count.Get(@class))
            {
                return;
            }
            var list  = VaList[(int)@class];
            var count = Count.Get(@class);

            var  state = VariableContext.State;
            bool didWork;

            do
            {
                didWork = false;
                for (var i = 0; i < count; i++)
                {
                    var aVa = list[i];
                    var aVd = aVa.VariableData;

                    if ((aVa.Flags & (VariableFlags.RReg | VariableFlags.AllocRDone)) != VariableFlags.RReg)
                    {
                        continue;
                    }

                    var aIndex = aVd.RegisterIndex;
                    var bIndex = aVa.InRegIndex;

                    // Shouldn't be the same.
                    if (!(aIndex != bIndex))
                    {
                        throw new ArgumentException();
                    }

                    var bVd = state.GetListByClass(@class)[bIndex];
                    if (bVd != null)
                    {
                        // Gp registers only - Swap two registers if we can solve two
                        // allocation tasks by a single 'xchg' instruction, swapping
                        // two registers required by the instruction/node or one register
                        // required with another non-required.
                        if (@class != RegisterClass.Gp || aIndex == RegisterIndex.Invalid)
                        {
                            continue;
                        }
                        var bVa = bVd.Attributes;
                        Translator.SwapGp(aVd, bVd);

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        // Doublehit, two registers allocated by a single swap.
                        if (bVa != null && bVa.InRegIndex == aIndex)
                        {
                            bVa.Flags |= VariableFlags.AllocRDone;
                            Done.Add(@class);
                        }

                        didWork = true;
                    }
                    else if (aIndex != RegisterIndex.Invalid)
                    {
                        Translator.Move(aVd, @class, bIndex);

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        didWork = true;
                    }
                    else
                    {
                        Translator.Alloc(aVd, @class, bIndex);

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        didWork = true;
                    }
                }
            } while (didWork);

            // Alloc 'out' regs.
            for (var i = 0; i < count; i++)
            {
                var va = list[i];
                var vd = va.VariableData;

                if ((va.Flags & (VariableFlags.XReg | VariableFlags.AllocWDone)) != VariableFlags.WReg)
                {
                    continue;
                }

                var regIndex = va.OutRegIndex;
                if (!(regIndex != RegisterIndex.Invalid))
                {
                    throw new ArgumentException();
                }

                if (vd.RegisterIndex != regIndex)
                {
                    if (!(state.GetListByClass(@class)[regIndex] == null))
                    {
                        throw new ArgumentException();
                    }
                    Translator.Attach(vd, @class, regIndex, false);
                }

                va.Flags |= VariableFlags.AllocWDone;
                Done.Add(@class);
            }
        }