Beispiel #1
0
        public void LeaveInvariant(HashSet <TKey> keys)
        {
#if DEBUG
            var liveKeys = GetLiveKeys();
            ContractHelpers.Assert(keys.IsSubsetOf(liveKeys));
#endif
        }
Beispiel #2
0
 /// <summary>
 /// Gets the constrained call instruction prototype for a particular callee.
 /// </summary>
 /// <param name="callee">The method to call.</param>
 /// <returns>A constrained call instruction prototype.</returns>
 public static ConstrainedCallPrototype Create(IMethod callee)
 {
     ContractHelpers.Assert(
         !callee.IsStatic,
         "Constrained calls cannot call static methods.");
     return(instanceCache.Intern(new ConstrainedCallPrototype(callee)));
 }
Beispiel #3
0
 /// <summary>
 /// Removes the instruction with a particular tag from
 /// this basic block. Returns a new basic block in a new
 /// control-flow graph.
 /// </summary>
 /// <param name="tag">The tag of the instruction to remove.</param>
 /// <returns>A new basic block in a new control-flow graph.</returns>
 public BasicBlock RemoveInstruction(ValueTag tag)
 {
     ContractHelpers.Assert(
         Graph.GetValueParent(tag).Tag == this.Tag,
         "Basic block does not define the instruction being removed.");
     return(Graph.RemoveInstruction(tag).GetBasicBlock(this.Tag));
 }
Beispiel #4
0
        /// <summary>
        /// Tells if a particular instruction is dominated by another instruction,
        /// that is, if control cannot flow to the instruction unless it first flowed
        /// through the dominator instruction.
        /// </summary>
        /// <param name="instruction">
        /// An instruction that might be dominated by <paramref name="dominator"/>.
        /// </param>
        /// <param name="dominator">
        /// An instruction that might dominate <paramref name="instruction"/>.
        /// </param>
        /// <returns>
        /// <c>true</c> if <paramref name="instruction"/> is strictly dominated by
        /// <paramref name="dominator"/> or <paramref name="instruction"/> equals
        /// <paramref name="dominator"/>; otherwise, <c>false</c>.
        /// </returns>
        public bool IsDominatedBy(NamedInstruction instruction, NamedInstruction dominator)
        {
            var graph = instruction.Block.Graph;

            ContractHelpers.Assert(graph == dominator.Block.Graph);
            return(IsDominatedBy(instruction, dominator, graph));
        }
Beispiel #5
0
 /// <summary>
 /// Gets the call instruction prototype for a particular callee.
 /// </summary>
 /// <param name="callee">The method to call.</param>
 /// <param name="lookup">The method lookup strategy for the call.</param>
 /// <returns>A call instruction prototype.</returns>
 public static CallPrototype Create(IMethod callee, MethodLookup lookup)
 {
     ContractHelpers.Assert(
         lookup == MethodLookup.Static || !callee.IsStatic,
         "A static callee method cannot be resolved via virtual lookup.");
     return(instanceCache.Intern(new CallPrototype(callee, lookup)));
 }
Beispiel #6
0
        /// <summary>
        /// Creates an integer value from the given integer and an integer spec.
        /// </summary>
        public IntegerConstant(BigInteger value, IntegerSpec spec)
        {
            ContractHelpers.Assert(spec != null);

            this.Value = value;
            this.Spec  = spec;
        }
Beispiel #7
0
 /// <summary>
 /// Reads out an integer spec attribute as an integer spec.
 /// </summary>
 /// <param name="attribute">The integer spec attribute to read.</param>
 /// <returns>The integer spec described by the attribute.</returns>
 public static IntegerSpec Read(IntrinsicAttribute attribute)
 {
     ContractHelpers.Assert(attribute.Name == AttributeName);
     ContractHelpers.Assert(attribute.Arguments.Count == 2);
     return(new IntegerSpec(
                ((IntegerConstant)attribute.Arguments[0]).ToInt32(),
                ((IntegerConstant)attribute.Arguments[1]).ToBoolean()));
 }
Beispiel #8
0
        /// <summary>
        /// "Normalizes" the given value, by casting it to this integer spec,
        /// from this integer spec. The result of this operation is always
        /// representible, even if the input value is not.
        /// </summary>
        public BigInteger Normalize(BigInteger value)
        {
            var result = Cast(value, this);

            AssertIsRepresentible(result);
            ContractHelpers.Assert(!IsRepresentible(value) || value.Equals(result));
            return(result);
        }
Beispiel #9
0
        /// <summary>
        /// Casts this integer value to match the given spec.
        /// </summary>
        public IntegerConstant Cast(IntegerSpec newSpec)
        {
            var result = new IntegerConstant(newSpec.Cast(Value, Spec), newSpec);

            ContractHelpers.Assert(result.Spec.Equals(newSpec));
            AssertIsValid(result);
            return(result);
        }
        /// <summary>
        /// Adds a generic parameter to this generic member.
        /// </summary>
        /// <param name="genericParameter">The generic parameter to add.</param>
        public void AddGenericParameter(IGenericParameter genericParameter)
        {
            ContractHelpers.Assert(
                object.Equals(this, genericParameter.ParentMember),
                "Generic parameters can only be added to their declaring member.");

            genericParamList.Add(genericParameter);
        }
 /// <summary>
 /// Gets the new-object instruction prototype for a particular constructor.
 /// </summary>
 /// <param name="constructor">The constructor to initialize objects with.</param>
 /// <returns>A new-object instruction prototype.</returns>
 public static NewObjectPrototype Create(IMethod constructor)
 {
     ContractHelpers.Assert(
         constructor.IsConstructor && !constructor.IsStatic,
         "A new-object instruction prototype's constructor method " +
         "must be an instance constructor.");
     return(instanceCache.Intern(new NewObjectPrototype(constructor)));
 }
Beispiel #12
0
        /// <summary>
        /// Adds a nested type to this type.
        /// </summary>
        /// <param name="nestedType">The nested type to add.</param>
        public void AddNestedType(IType nestedType)
        {
            ContractHelpers.Assert(
                nestedType.Parent.IsType,
                "Cannot add a non-nested type as a nested type.");

            ContractHelpers.Assert(
                object.Equals(this, nestedType.Parent.Type),
                "A nested type can only be added to its defining type.");
            nestedTypeList.Add(nestedType);
        }
Beispiel #13
0
        internal BasicBlock UpdateBasicBlockParameters(
            BasicBlockTag tag,
            ImmutableList <BlockParameter> parameters)
        {
            AssertContainsBasicBlock(tag);
            var oldBlock = blocks[tag];

            var newData = new BasicBlockData(
                parameters,
                oldBlock.InstructionTags,
                oldBlock.Flow);

            var oldData   = blocks[tag];
            var oldParams = oldData.Parameters;

            var newGraph = new FlowGraph(this, new BasicBlockParametersUpdate(tag));

            var paramTypeBuilder   = newGraph.blockParamTypes.ToBuilder();
            var valueParentBuilder = newGraph.valueParents.ToBuilder();

            // Remove the basic block's parameters from the value parent
            // and parameter type dictionaries.
            int oldParamCount = oldParams.Count;

            for (int i = 0; i < oldParamCount; i++)
            {
                paramTypeBuilder.Remove(oldParams[i].Tag);
                valueParentBuilder.Remove(oldParams[i].Tag);
            }

            // Add the new basic block parameters to the value parent and
            // parameter type dictionaries.
            int newParamCount = parameters.Count;

            for (int i = 0; i < newParamCount; i++)
            {
                var item = parameters[i];

                ContractHelpers.Assert(
                    !valueParentBuilder.ContainsKey(item.Tag),
                    "Value tag '" + item.Tag.Name + "' cannot appear twice in the same control-flow graph.");

                paramTypeBuilder.Add(item.Tag, item.Type);
                valueParentBuilder.Add(item.Tag, tag);
            }

            newGraph.blockParamTypes = paramTypeBuilder.ToImmutable();
            newGraph.valueParents    = valueParentBuilder.ToImmutable();
            newGraph.blocks          = newGraph.blocks.SetItem(tag, newData);

            return(new BasicBlock(newGraph, tag, newData));
        }
Beispiel #14
0
        /// <inheritdoc/>
        public override BlockFlow WithInstructions(IReadOnlyList <Instruction> instructions)
        {
            ContractHelpers.Assert(instructions.Count == 1, "Switch flow takes exactly one instruction.");
            var newSwitchValue = instructions[0];

            if (object.ReferenceEquals(newSwitchValue, SwitchValue))
            {
                return(this);
            }
            else
            {
                return(new SwitchFlow(newSwitchValue, Cases, DefaultBranch));
            }
        }
Beispiel #15
0
        /// <inheritdoc/>
        public override BlockFlow WithInstructions(IReadOnlyList <Instruction> instructions)
        {
            ContractHelpers.Assert(instructions.Count == 1, "Try flow takes exactly one instruction.");
            var insn = instructions[0];

            if (insn == Instruction)
            {
                return(this);
            }
            else
            {
                return(new TryFlow(insn, SuccessBranch, ExceptionBranch));
            }
        }
Beispiel #16
0
        /// <inheritdoc/>
        public override BlockFlow WithInstructions(IReadOnlyList <Instruction> instructions)
        {
            ContractHelpers.Assert(instructions.Count == 1, "Return flow takes exactly one instruction.");
            var newReturnValue = instructions[0];

            if (object.ReferenceEquals(newReturnValue, ReturnValue))
            {
                return(this);
            }
            else
            {
                return(new ReturnFlow(newReturnValue));
            }
        }
Beispiel #17
0
        /// <inheritdoc/>
        public override BlockFlow WithBranches(IReadOnlyList <Branch> branches)
        {
            ContractHelpers.Assert(branches.Count == 1, "Jump flow takes exactly one branch.");
            var newBranch = branches[0];

            if (object.ReferenceEquals(newBranch, Branch))
            {
                return(this);
            }
            else
            {
                return(new JumpFlow(newBranch));
            }
        }
Beispiel #18
0
        /// <inheritdoc/>
        public override BlockFlow WithBranches(IReadOnlyList <Branch> branches)
        {
            ContractHelpers.Assert(branches.Count == 2, "Try flow takes exactly two branches.");
            var success = branches[0];
            var exn     = branches[1];

            if (success == SuccessBranch && exn == ExceptionBranch)
            {
                return(this);
            }
            else
            {
                return(new TryFlow(Instruction, success, exn));
            }
        }
Beispiel #19
0
        /// <summary>
        /// Cleans up all buckets allocated to a particular concurrency
        /// domain.
        /// </summary>
        /// <param name="concurrencyDomain">
        /// The concurrency domain whose buckets are to be cleaned.
        /// </param>
        /// <remarks>
        /// This method is thread-safe within a single concurrency domain.
        /// </remarks>
        private void Cleanup(int concurrencyDomain)
        {
            for (int i = concurrencyDomain; i < buckets.Length; i += MaxConcurrency)
            {
                ContractHelpers.Assert(GetConcurrencyDomain(i) == concurrencyDomain);

                var  bucket   = buckets[i];
                bool wasEmpty = bucket.IsEmpty;
                bucket.Cleanup();
                if (!wasEmpty && bucket.IsEmpty)
                {
                    Interlocked.Decrement(ref initializedBucketCount);
                }
                buckets[i] = bucket;
            }
        }
Beispiel #20
0
        /// <summary>
        /// Casts the given unsigned integer to match this spec.
        /// </summary>
        private BigInteger CastUnsigned(BigInteger value)
        {
            // We're dealing with a positive integer, so first, we'll make
            // sure it fits in the number of bits we have.
            ContractHelpers.Assert(value.Sign >= 0);
            var remainder = BigInteger.Remainder(value, UnsignedModulus);

            if (remainder.CompareTo(MaxValue) > 0)
            {
                // We're dealing with two's complement here.
                return(BigInteger.Subtract(BigInteger.Remainder(remainder, Modulus), Modulus));
            }
            else
            {
                // Unsigned number. Just return the remainder.
                return(remainder);
            }
        }
Beispiel #21
0
        /// <summary>
        /// Creates an integer size from the given number of bits,
        /// and signedness.
        /// </summary>
        public IntegerSpec(int size, bool isSigned)
        {
            this.Size     = size;
            this.IsSigned = isSigned;

            ContractHelpers.Assert(size > 0);

            this.UnsignedModulus = BigInteger.Pow(new BigInteger((int)2), size);
            this.Modulus         = BigInteger.Pow(new BigInteger((int)2), DataSize);
            this.MaxValue        = BigInteger.Subtract(Modulus, BigInteger.One);

            if (isSigned)
            {
                this.MinValue = BigInteger.Negate(Modulus);
            }
            else
            {
                this.MinValue = BigInteger.Zero;
            }
        }
Beispiel #22
0
        /// <inheritdoc/>
        public override BlockFlow WithBranches(IReadOnlyList <Branch> branches)
        {
            int branchCount = branches.Count;
            int caseCount   = Cases.Count;

            ContractHelpers.Assert(
                branchCount == caseCount + 1,
                "Got '" + branchCount +
                "' branches when re-creating a switch statement, but expected '" +
                (caseCount + 1) + "'.");

            var newCases = new SwitchCase[caseCount];

            for (int i = 0; i < caseCount; i++)
            {
                newCases[i] = new SwitchCase(Cases[i].Values, branches[i]);
            }

            return(new SwitchFlow(
                       SwitchValue,
                       newCases,
                       branches[caseCount]));
        }
        /// <summary>
        /// Gets or creates a new-delegate instruction prototype.
        /// </summary>
        /// <param name="delegateType">
        /// The type of delegate produced by instances of the prototype.
        /// </param>
        /// <param name="callee">
        /// The method that is invoked when the delegates produced by instances
        /// of the prototype are called.
        /// </param>
        /// <param name="hasThisArgument">
        /// Tells if a 'this' argument is included in the delegate.
        /// </param>
        /// <param name="lookup">
        /// The method lookup strategy for the prototype.
        /// </param>
        /// <returns>A new-delegate instruction prototype.</returns>
        public static NewDelegatePrototype Create(
            IType delegateType,
            IMethod callee,
            bool hasThisArgument,
            MethodLookup lookup)
        {
            if (hasThisArgument)
            {
                ContractHelpers.Assert(
                    !callee.IsStatic || callee.Parameters.Count >= 1,
                    "A callee that is provided a 'this' argument must " +
                    "be an instance method or take at least one parameter.");
            }
            ContractHelpers.Assert(
                lookup == MethodLookup.Static || !callee.IsStatic,
                "A static callee method cannot be resolved via virtual lookup.");

            return(instanceCache.Intern(
                       new NewDelegatePrototype(
                           delegateType,
                           callee,
                           hasThisArgument,
                           lookup)));
        }
Beispiel #24
0
 /// <inheritdoc/>
 public override BlockFlow WithBranches(IReadOnlyList <Branch> branches)
 {
     ContractHelpers.Assert(branches.Count == 0, "Unreachable flow does not take any branches.");
     return(this);
 }
Beispiel #25
0
 /// <inheritdoc/>
 public override BlockFlow WithInstructions(IReadOnlyList <Instruction> instructions)
 {
     ContractHelpers.Assert(instructions.Count == 0, "Unreachable flow does not take any instructions.");
     return(this);
 }
Beispiel #26
0
 /// <summary>
 /// Asserts that a particular instruction is an instance of
 /// this prototype.
 /// </summary>
 /// <param name="instruction">The instruction to examine.</param>
 /// <param name="errorMessage">
 /// An error message to print if the assertion does not hold true.
 /// </param>
 public void AssertIsPrototypeOf(Instruction instruction, string errorMessage)
 {
     ContractHelpers.Assert(IsPrototypeOf(instruction), errorMessage);
 }
 /// <summary>
 /// Gets the 'this' argument in an instruction that conforms to
 /// this prototype.
 /// </summary>
 /// <param name="instruction">
 /// An instruction that conforms to this prototype.
 /// </param>
 /// <returns>The 'this' argument.</returns>
 public ValueTag GetThisArgument(Instruction instruction)
 {
     AssertIsPrototypeOf(instruction);
     ContractHelpers.Assert(HasThisArgument);
     return(instruction.Arguments[0]);
 }
Beispiel #28
0
 private void CheckParent(ITypeMember member)
 {
     ContractHelpers.Assert(
         object.Equals(this, member.ParentType),
         "A member can only be added to its defining type.");
 }
Beispiel #29
0
 /// <summary>
 /// Instantiates this prototype with a list of arguments.
 /// </summary>
 /// <param name="arguments">
 /// The arguments to instantiate this prototype with.
 /// </param>
 /// <returns>
 /// An instruction whose prototype is equal to this prototype
 /// and whose argument list is <paramref name="arguments"/>.
 /// </returns>
 public Instruction Instantiate(IReadOnlyList <ValueTag> arguments)
 {
     ContractHelpers.Assert(arguments.Count == ParameterCount);
     return(new Instruction(this, arguments));
 }
Beispiel #30
0
 private BigInteger AssertIsRepresentible(BigInteger value)
 {
     ContractHelpers.Assert(IsRepresentible(value));
     return(value);
 }