示例#1
0
        private Result OnFetchLabel()
        {
            var node = _node.As <LabelNode>();

            if (node != _functionNode.Exit)
            {
                return(Result.Break);
            }
            _variableContext.ReturningList.Add(node);
            return(Result.NextGroup);
        }
示例#2
0
        private static void AfterRemoveNode(CodeNode node)
        {
            if (!node.Flags.IsSet(CodeNodeFlags.Jmp | CodeNodeFlags.Jcc))
            {
                return;
            }

            var jj = new ValueSet <CodeNode, JumpNode>();

            var jump  = node.As <JumpNode>();
            var label = jump.Target;

            if (label == null)
            {
                return;
            }
            // Disconnect.
            jj.Value0 = label;
            jj.Value1 = label.From;
            for (; ;)
            {
                var current = jj;
                if (current.Value1 == null)
                {
                    break;
                }

                if (current.Value1 == jump)
                {
                    jj.Value0 = jump;
                    jj.Value1 = jump.NextJump;
                    break;
                }

                jj.Value1 = current.Value1;
            }
            if (jj.Value0.Type == CodeNodeType.Label)
            {
                jj.Value0.As <LabelNode>().From = jj.Value1;
            }
            else
            {
                jj.Value0.As <JumpNode>().NextJump = jj.Value1;
            }
            label.ReferenceCount--;
        }
示例#3
0
        private void OnTarget(CodeNode node, JumpNode from, LivenessTarget ltCur, LivenessTarget ltUnused, BitArray bCur, int bLen, ref int retPtr, bool jumpNext = false)
        {
            var label = node.As <LabelNode>();

            if (label.ReferenceCount != 0 || jumpNext)
            {
                if (!jumpNext)
                {
                    // Push a new LivenessTarget onto the stack if needed.
                    if (ltCur == null || ltCur.Node != node)
                    {
                        // Allocate a new LivenessTarget object (from pool or zone).
                        var ltTmp = ltUnused;

                        if (ltTmp != null)
                        {
                            ltUnused = ltUnused.Previous;
                        }
                        else
                        {
                            ltTmp = new LivenessTarget();
                        }

                        // Initialize and make current - ltTmp->from will be set later on.
                        ltTmp.Previous = ltCur;
                        ltTmp.Node     = label;
                        ltCur          = ltTmp;

                        from = label.From;
                        if (from == null)
                        {
                            throw new ArgumentNullException();
                        }
                    }
                    else
                    {
                        from = ltCur.From;
                        OnTarget(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr, true);
                        return;
                        //					goto _OnJumpNext;
                    }
                }

                // Visit/Patch.
                do
                {
                    if (!jumpNext)
                    {
                        ltCur.From = from;
                        bCur.CopyBits(node.Liveness, bLen);

                        if (from.Liveness == null)
                        {
                            node = from;
                            OnVisit(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr);
                        }
                        //						jumpNext = true;
                    }

                    // Issue #25: Moved '_OnJumpNext' here since it's important to patch
                    // code again if there are more live variables than before.
                    jumpNext = false;
                    if (bCur.DelBits(from.Liveness, bLen))
                    {
                        node = from;
                        OnPatch(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr);
                        return;
                    }

                    from = from.NextJump;
                } while (from != null);

                {
                    // Pop the current LivenessTarget from the stack.
                    var ltTmp = ltCur;

                    ltCur          = ltCur.Previous;
                    ltTmp.Previous = ltUnused;
                    ltUnused       = ltTmp;
                }
            }

            bCur.CopyBits(node.Liveness, bLen);
            node = node.Previous;

            if (node.Flags.IsSet(CodeNodeFlags.Jmp) || !node.IsFetched())
            {
                OnDone(from, ltCur, ltUnused, bCur, bLen, ref retPtr);
                return;
            }

            if (node.Liveness == null)
            {
                OnVisit(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr);
                return;
            }

            if (bCur.DelBits(node.Liveness, bLen))
            {
                OnPatch(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr);
                return;
            }
            OnDone(from, ltCur, ltUnused, bCur, bLen, ref retPtr);
        }
示例#4
0
        public void Run(CodeNode node)
        {
            var map = node.VariableMap;

            if (map == null)
            {
                return;
            }

            InitImpl(node, map);

            UnuseBefore(RegisterClass.Gp);
            UnuseBefore(RegisterClass.Mm);
            UnuseBefore(RegisterClass.Xyz);

            Plan(RegisterClass.Gp);
            Plan(RegisterClass.Mm);
            Plan(RegisterClass.Xyz);

            Spill(RegisterClass.Gp);
            Spill(RegisterClass.Mm);
            Spill(RegisterClass.Xyz);

            Alloc(RegisterClass.Gp);
            Alloc(RegisterClass.Mm);
            Alloc(RegisterClass.Xyz);

            // Translate node operands.
            if (node.Type == CodeNodeType.Instruction)
            {
                var inst = node.As <InstructionNode>();
                Translator.TranslateOperands(inst.Operands);
            }
            else if (node.Type == CodeNodeType.CallArgument)
            {
                var carg = node.As <CallArgumentNode>();

                var call = carg.Call;
                var decl = call.FunctionDeclaration;

                var argIndex = 0;
                var argMask  = carg.AffectedArguments;

                var sVd = carg.Source;
                var cVd = carg.Conv;

                // Convert first.
                if (!(sVd.RegisterIndex != RegisterIndex.Invalid))
                {
                    throw new ArgumentException();
                }

                if (cVd != null)
                {
                    if (!(cVd.RegisterIndex != RegisterIndex.Invalid))
                    {
                        throw new ArgumentException();
                    }
                    Translator.EmitConvertVarToVar(cVd.Type, cVd.RegisterIndex, sVd.Type, sVd.RegisterIndex);
                    sVd = cVd;
                }

                while (argMask != 0)
                {
                    if (argMask.IsSet(0x1))
                    {
                        var arg = decl.GetArgument(argIndex);
                        if (!(arg.StackOffset != Constants.InvalidValue))
                        {
                            throw new ArgumentException();
                        }

                        var dst = Memory.Ptr(Assembler.Zsp, -Cpu.Info.RegisterSize + arg.StackOffset);
                        Translator.EmitMoveVarOnStack(arg.VariableType, dst, sVd.Type, sVd.RegisterIndex);
                    }

                    argIndex++;
                    argMask >>= 1;
                }
            }

            // Mark variables as modified.
            Modified(RegisterClass.Gp);
            Modified(RegisterClass.Mm);
            Modified(RegisterClass.Xyz);

            // Cleanup; disconnect Vd->Va.
            Cleanup();

            // Update clobbered mask.
            VariableContext.ClobberedRegs.Or(_willAlloc);
            VariableContext.ClobberedRegs.Or(map.ClobberedRegs);

            // Unuse.
            UnuseAfter(RegisterClass.Gp);
            UnuseAfter(RegisterClass.Mm);
            UnuseAfter(RegisterClass.Xyz);
        }