Пример #1
0
        /// <summary>
        /// <para>Pops a value off the stack and branches to the label at the index of that value in the given labels.</para>
        /// <para>If the value is out of range, execution falls through to the next instruction.</para>
        /// </summary>
        public Emit <DelegateType> Switch(params Label[] labels)
        {
            if (labels == null)
            {
                throw new ArgumentNullException("labels");
            }

            if (labels.Length == 0)
            {
                throw new ArgumentException("labels must have at least one element");
            }

            if (LinqAlternative.Any(labels, l => ((IOwned)l).Owner is DisassembledOperations <DelegateType>))
            {
                return
                    (Switch(LinqAlternative.Select(labels, l => l.Name).ToArray()));
            }

            foreach (var label in labels)
            {
                if (((IOwned)label).Owner != this)
                {
                    FailOwnership(label);
                }
            }

            foreach (var label in labels)
            {
                UnusedLabels.Remove(label);
            }

            var transitions =
                new[]
            {
                new StackTransition(new [] { typeof(int) }, TypeHelpers.EmptyTypes),
                new StackTransition(new [] { typeof(NativeIntType) }, TypeHelpers.EmptyTypes),
            };

            var labelsCopy = ((LinqArray <Label>)labels).Select(l => l).ToArray();

            UpdateOpCodeDelegate update;

            UpdateState(OpCodes.Switch, labelsCopy, Wrap(transitions, "Switch"), out update);

            var valid = CurrentVerifiers.ConditionalBranch(labels);

            if (!valid.Success)
            {
                throw new SigilVerificationException("Switch", valid, IL.Instructions(AllLocals));
            }

            foreach (var label in labels)
            {
                Branches.Add(SigilTuple.Create(OpCodes.Switch, label, IL.Index));
                BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Switch);
            }

            return(this);
        }
Пример #2
0
        /// <summary>
        /// <para>Pops one argument from the stack, branches to the given label if the value is true.</para>
        /// <para>A value is true if it is non-zero or non-null.</para>
        /// </summary>
        public Emit <DelegateType> BranchIfTrue(Label label)
        {
            if (label == null)
            {
                throw new ArgumentNullException("label");
            }

            if (((IOwned)label).Owner != this)
            {
                if (((IOwned)label).Owner is DisassembledOperations <DelegateType> )
                {
                    return(BranchIfTrue(label.Name));
                }

                FailOwnership(label);
            }

            UnusedLabels.Remove(label);

            var transitions =
                new[]
            {
                new StackTransition(new [] { typeof(WildcardType) }, TypeHelpers.EmptyTypes)
            };

            UpdateOpCodeDelegate update;

            UpdateState(OpCodes.Brtrue, label, Wrap(transitions, "BranchIfTrue"), out update);

            var valid = CurrentVerifiers.ConditionalBranch(label);

            if (!valid.Success)
            {
                throw new SigilVerificationException("BranchIfTrue", valid, IL.Instructions(AllLocals));
            }

            Branches.Add(SigilTuple.Create(OpCodes.Brtrue, label, IL.Index));

            BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Brtrue);

            return(this);
        }
Пример #3
0
        /// <summary>
        /// Defines a new label.
        ///
        /// This label can be used for branching, leave, and switch instructions.
        ///
        /// A label must be marked exactly once after being defined, using the MarkLabel() method.
        /// </summary>
        public Label DefineLabel(string name = null)
        {
            name = name ?? AutoNamer.Next(this, "_label", Locals.Names, Labels.Names);

            if (CurrentLabels.ContainsKey(name))
            {
                throw new InvalidOperationException("Label with name '" + name + "' already exists");
            }

            var label = IL.DefineLabel();

            var ret = new Label(this, label, name);

            UnusedLabels.Add(ret);
            UnmarkedLabels.Add(ret);

            CurrentLabels[name] = ret;

            return(ret);
        }
Пример #4
0
        /// <summary>
        /// Unconditionally branches to the given label.
        /// </summary>
        public Emit <DelegateType> Branch(Label label)
        {
            if (label == null)
            {
                throw new ArgumentNullException("label");
            }

            if (((IOwned)label).Owner != this)
            {
                if (((IOwned)label).Owner is DisassembledOperations <DelegateType> )
                {
                    return(Branch(label.Name));
                }

                FailOwnership(label);
            }

            UnusedLabels.Remove(label);

            UpdateOpCodeDelegate update;

            UpdateState(OpCodes.Br, label, Wrap(StackTransition.None(), "Branch"), out update);

            var valid = CurrentVerifiers.UnconditionalBranch(label);

            if (!valid.Success)
            {
                throw new SigilVerificationException("Branch", valid, IL.Instructions(AllLocals));
            }

            Branches.Add(SigilTuple.Create(OpCodes.Br, label, IL.Index));

            BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Br);

            MustMark = true;

            return(this);
        }
Пример #5
0
        /// <summary>
        /// Pops two arguments from the stack, branches to the given label if the second value is less than the first value (when treated as unsigned values).
        /// </summary>
        public Emit <DelegateType> UnsignedBranchIfLess(Label label)
        {
            if (label == null)
            {
                throw new ArgumentNullException("label");
            }

            if (((IOwned)label).Owner != this)
            {
                if (((IOwned)label).Owner is DisassembledOperations <DelegateType> )
                {
                    return(UnsignedBranchIfLess(label.Name));
                }

                FailOwnership(label);
            }

            UnusedLabels.Remove(label);

            UpdateOpCodeDelegate update;

            UpdateState(OpCodes.Blt_Un, label, BranchComparableTransitions("UnsignedBranchIfLess"), out update);

            var valid = CurrentVerifiers.ConditionalBranch(label);

            if (!valid.Success)
            {
                throw new SigilVerificationException("UnsignedBranchIfLess", valid, IL.Instructions(AllLocals));
            }

            Branches.Add(SigilTuple.Create(OpCodes.Blt_Un, label, IL.Index));

            BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Blt_Un);

            return(this);
        }