Beispiel #1
0
        // Various parsing functions for processing through the locals of a function and translating them to the
        // alternate form with new tokens.
        int ParseCompressedInt()
        {
            int value = _input.ReadCompressedInteger();

            _output.WriteCompressedInteger(value);
            return(value);
        }
Beispiel #2
0
        private unsafe static void ConvertConstantSignature(BlobBuilder builder, MetadataModel metadataModel, byte[] signature, object value)
        {
            fixed(byte *sigPtr = signature)
            {
                var sigReader = new BlobReader(sigPtr, signature.Length);

                // copy custom modifiers over:
                byte rawTypeCode;

                while (true)
                {
                    rawTypeCode = sigReader.ReadByte();
                    if (rawTypeCode != (int)SignatureTypeCode.OptionalModifier && rawTypeCode != (int)SignatureTypeCode.RequiredModifier)
                    {
                        break;
                    }

                    builder.WriteByte(rawTypeCode);
                    builder.WriteCompressedInteger(sigReader.ReadCompressedInteger());
                }

                switch ((SignatureTypeCode)rawTypeCode)
                {
                case (SignatureTypeCode)SignatureTypeKind.Class:
                case (SignatureTypeCode)SignatureTypeKind.ValueType:
                    int typeRefDefSpec = sigReader.ReadCompressedInteger();

                    if (value is decimal)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <decimal>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDecimal((decimal)value);
                    }
                    else if (value is double d)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <date-time>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDateTime(new DateTime(BitConverter.DoubleToInt64Bits(d)));
                    }
                    else if (value is 0 && rawTypeCode == (byte)SignatureTypeKind.Class)
                    {
                        // GeneralConstant: CLASS TypeDefOrRefOrSpecEncoded
                        builder.WriteByte(rawTypeCode);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }
                    else
                    {
                        // EnumConstant ::= EnumTypeCode EnumValue EnumType
                        // EnumTypeCode ::= BOOLEAN | CHAR | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8
                        // EnumType     ::= TypeDefOrRefOrSpecEncoded

                        var enumTypeCode = AssemblyDisplayNameBuilder.GetConstantTypeCode(value);
                        builder.WriteByte((byte)enumTypeCode);
                        builder.WriteConstant(value);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }

                    break;
 private void SerializeImport(BlobBuilder writer, AssemblyReferenceAlias alias)
 {
     // <import> ::= AliasAssemblyReference <alias> <target-assembly>
     writer.WriteByte((byte)ImportDefinitionKind.AliasAssemblyReference);
     writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(alias.Name)));
     writer.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetOrAddAssemblyReferenceHandle(alias.Assembly)));
 }
        private BlobHandle SerializeSpans(
            ImmutableArray <SourceSpan> spans,
            Dictionary <DebugSourceDocument, int> documentIndex)
        {
            if (spans.Length == 0)
            {
                return(default(BlobHandle));
            }

            // 4 bytes per span plus a header, the builder expands by the same amount.
            var writer = new BlobBuilder(4 + spans.Length * 4);

            int previousStartLine   = -1;
            int previousStartColumn = -1;
            DebugSourceDocument previousDocument = spans[0].Document;

            // header:
            writer.WriteCompressedInteger(GetOrAddDocument(previousDocument, documentIndex));

            for (int i = 0; i < spans.Length; i++)
            {
                var currentDocument = spans[i].Document;
                if (previousDocument != currentDocument)
                {
                    writer.WriteInt16(0);
                    writer.WriteCompressedInteger(GetOrAddDocument(currentDocument, documentIndex));
                    previousDocument = currentDocument;
                }

                // Delta Lines & Columns:
                SerializeDeltaLinesAndColumns(writer, spans[i]);

                // delta Start Lines & Columns:
                if (previousStartLine < 0)
                {
                    Debug.Assert(previousStartColumn < 0);
                    writer.WriteCompressedInteger(spans[i].StartLine);
                    writer.WriteCompressedInteger(spans[i].StartColumn);
                }
                else
                {
                    writer.WriteCompressedSignedInteger(spans[i].StartLine - previousStartLine);
                    writer.WriteCompressedSignedInteger(spans[i].StartColumn - previousStartColumn);
                }

                previousStartLine   = spans[i].StartLine;
                previousStartColumn = spans[i].StartColumn;
            }

            return(GetOrAddBlob(writer));
        }
        internal void SerializeLocalSlots(BlobBuilder writer)
        {
            int syntaxOffsetBaseline = -1;

            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                if (localSlot.Id.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = localSlot.Id.SyntaxOffset;
                }
            }

            if (syntaxOffsetBaseline != -1)
            {
                writer.WriteByte(SyntaxOffsetBaseline);
                writer.WriteCompressedInteger(-syntaxOffsetBaseline);
            }

            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                SynthesizedLocalKind kind = localSlot.SynthesizedKind;
                Debug.Assert(kind <= SynthesizedLocalKind.MaxValidValueForLocalVariableSerializedToDebugInformation);

                if (!kind.IsLongLived())
                {
                    writer.WriteByte(0);
                    continue;
                }

                byte b = (byte)(kind + 1);
                Debug.Assert((b & (1 << 7)) == 0);

                bool hasOrdinal = localSlot.Id.Ordinal > 0;

                if (hasOrdinal)
                {
                    b |= 1 << 7;
                }

                writer.WriteByte(b);
                writer.WriteCompressedInteger(localSlot.Id.SyntaxOffset - syntaxOffsetBaseline);

                if (hasOrdinal)
                {
                    writer.WriteCompressedInteger(localSlot.Id.Ordinal);
                }
            }
        }
Beispiel #6
0
        void EncodeMethodSignature(BlobBuilder signatureBuilder, MethodSignature sig)
        {
            BlobEncoder signatureEncoder      = new BlobEncoder(signatureBuilder);
            int         genericParameterCount = sig.GenericParameterCount;
            bool        isInstanceMethod      = !sig.IsStatic;
            SignatureCallingConvention sigCallingConvention = SignatureCallingConvention.Default;

            switch (sig.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask)
            {
            case MethodSignatureFlags.CallingConventionVarargs:
                sigCallingConvention = SignatureCallingConvention.VarArgs;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionCdecl:
                sigCallingConvention = SignatureCallingConvention.CDecl;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionStdCall:
                sigCallingConvention = SignatureCallingConvention.StdCall;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionThisCall:
                sigCallingConvention = SignatureCallingConvention.ThisCall;
                break;
            }

            signatureEncoder.MethodSignature(sigCallingConvention, genericParameterCount, isInstanceMethod);
            signatureBuilder.WriteCompressedInteger(sig.Length);
            // TODO Process custom modifiers in some way
            EncodeType(signatureBuilder, sig.ReturnType);
            for (int i = 0; i < sig.Length; i++)
            {
                EncodeType(signatureBuilder, sig[i]);
            }
        }
Beispiel #7
0
        private static byte[] CompressUnsignedInteger(int value)
        {
            var writer = new BlobBuilder();

            writer.WriteCompressedInteger((uint)value);
            return(writer.ToArray());
        }
        public void WriteSequencePoints(SequencePoint[] sequencePoints)
        {
            if (sequencePoints.Length == 0)
            {
                return;
            }
            BlobBuilder blobBuilder = Builder;
            int         num         = -1;
            int         num2        = -1;

            blobBuilder.WriteCompressedInteger(LocalSignatureRowId);
            DocumentHandle debugSourceDocument = sequencePoints[0].Document;

            for (int i = 0; i < sequencePoints.Length; i++)
            {
                DocumentHandle document = sequencePoints[i].Document;
                if (debugSourceDocument != document)
                {
                    if (debugSourceDocument != null)
                    {
                        blobBuilder.WriteCompressedInteger(0);
                    }
                    blobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(document));
                    debugSourceDocument = document;
                }
                if (i > 0)
                {
                    if (sequencePoints[i].Offset - sequencePoints[i - 1].Offset < 1)
                    {
                        throw new InvalidOperationException("There must not be specified more sequence points per offset.");
                    }

                    blobBuilder.WriteCompressedInteger(sequencePoints[i].Offset - sequencePoints[i - 1].Offset);
                }
                else
                {
                    blobBuilder.WriteCompressedInteger(sequencePoints[i].Offset);
                }
                if (sequencePoints[i].IsHidden)
                {
                    blobBuilder.WriteInt16(0);
                }
                else
                {
                    this.SerializeDeltaLinesAndColumns(blobBuilder, sequencePoints[i]);
                    if (num < 0)
                    {
                        blobBuilder.WriteCompressedInteger(sequencePoints[i].StartLine);
                        blobBuilder.WriteCompressedInteger(sequencePoints[i].StartColumn);
                    }
                    else
                    {
                        blobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartLine - num);
                        blobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartColumn - num2);
                    }
                    num  = sequencePoints[i].StartLine;
                    num2 = sequencePoints[i].StartColumn;
                }
            }
        }
        public void AllowUseOfAddGlobalMethod()
        {
            BlobBuilder noArgsNoReturnStaticMethodSig = new BlobBuilder();
            BlobEncoder signatureEncoder = new BlobEncoder(noArgsNoReturnStaticMethodSig);

            signatureEncoder.MethodSignature(SignatureCallingConvention.Default, 0, false);
            noArgsNoReturnStaticMethodSig.WriteCompressedInteger(0);
            noArgsNoReturnStaticMethodSig.WriteByte((byte)SignatureTypeCode.Void);
            _noArgsVoidReturnStaticMethodSigHandle = _metadataBuilder.GetOrAddBlob(noArgsNoReturnStaticMethodSig);
        }
        private static void SerializeDeltaLinesAndColumns(BlobBuilder writer, SymUnmanagedSequencePoint sequencePoint)
        {
            int deltaLines   = sequencePoint.EndLine - sequencePoint.StartLine;
            int deltaColumns = sequencePoint.EndColumn - sequencePoint.StartColumn;

            // only hidden sequence points have zero width
            Debug.Assert(deltaLines != 0 || deltaColumns != 0 || sequencePoint.IsHidden);

            writer.WriteCompressedInteger(deltaLines);

            if (deltaLines == 0)
            {
                writer.WriteCompressedInteger(deltaColumns);
            }
            else
            {
                writer.WriteCompressedSignedInteger(deltaColumns);
            }
        }
        private void SerializeDeltaLinesAndColumns(BlobBuilder writer, SourceSpan span)
        {
            int deltaLines   = span.EndLine - span.StartLine;
            int deltaColumns = span.EndColumn - span.StartColumn;

            // spans can't have zero width
            Debug.Assert(deltaLines != 0 || deltaColumns != 0);

            writer.WriteCompressedInteger(deltaLines);

            if (deltaLines == 0)
            {
                writer.WriteCompressedInteger(deltaColumns);
            }
            else
            {
                writer.WriteCompressedSignedInteger(deltaColumns);
            }
        }
Beispiel #12
0
    /// Just write the dictionary out to a blob as a count followed by
    /// a length-prefixed UTF8 encoding of each key and value
    private void ConvertDictionaryToBlob(IReadOnlyDictionary <string, string> properties, BlobBuilder builder)
    {
        int count = properties.Count;

        builder.WriteCompressedInteger(count);
        foreach (var kvp in properties)
        {
            builder.WriteSerializedString(kvp.Key);
            builder.WriteSerializedString(kvp.Value);
        }
    }
        public void CompressUnsignedIntegersFromSpecExamples()
        {
            // These examples are straight from the CLI spec.

            TestCompressedUnsignedInteger(new byte[] { 0x00 }, 0);
            TestCompressedUnsignedInteger(new byte[] { 0x03 }, 0x03);
            TestCompressedUnsignedInteger(new byte[] { 0x7f }, 0x7F);
            TestCompressedUnsignedInteger(new byte[] { 0x80, 0x80 }, 0x80);
            TestCompressedUnsignedInteger(new byte[] { 0xAE, 0x57 }, 0x2E57);
            TestCompressedUnsignedInteger(new byte[] { 0xBF, 0xFF }, 0x3FFF);
            TestCompressedUnsignedInteger(new byte[] { 0xC0, 0x00, 0x40, 0x00 }, 0x4000);
            TestCompressedUnsignedInteger(new byte[] { 0xDF, 0xFF, 0xFF, 0xFF }, 0x1FFFFFFF);

            var writer  = new BlobWriter(4);
            var builder = new BlobBuilder();

            Assert.Throws <ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(-1));
            Assert.Throws <ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1));
            Assert.Throws <ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(-1));
            Assert.Throws <ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1));
        }
Beispiel #14
0
        // TODO:
        // WriteBytes(byte*)
        // WriteBytes(stream)
        // WriteBytes(byte[])
        // WriteBytes(IA<byte>)
        // WriteReference

        private static void TestCompressedUnsignedInteger(byte[] expected, int value)
        {
            var writer = new BlobWriter(4);

            writer.WriteCompressedInteger(value);
            AssertEx.Equal(expected, writer.ToArray());

            var builder = new BlobBuilder();

            builder.WriteCompressedInteger(value);
            AssertEx.Equal(expected, builder.ToArray());
        }
            public void EmitAtCurrentIndexStack(BlobBuilder signatureBuilder)
            {
                if (!Complete)
                {
                    if (_embeddedDataIndex < _embeddedData.Length)
                    {
                        string indexData = string.Join(".", _indexStack);
                        while ((_embeddedDataIndex < _embeddedData.Length) && _embeddedData[_embeddedDataIndex].index == indexData)
                        {
                            switch (_embeddedData[_embeddedDataIndex].kind)
                            {
                            case EmbeddedSignatureDataKind.OptionalCustomModifier:
                            {
                                signatureBuilder.WriteByte((byte)SignatureTypeCode.OptionalModifier);
                                EntityHandle handle = _metadataEmitter.GetTypeRef((MetadataType)_embeddedData[_embeddedDataIndex].type);
                                signatureBuilder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(handle));
                            }
                            break;

                            case EmbeddedSignatureDataKind.RequiredCustomModifier:
                            {
                                signatureBuilder.WriteByte((byte)SignatureTypeCode.RequiredModifier);
                                EntityHandle handle = _metadataEmitter.GetTypeRef((MetadataType)_embeddedData[_embeddedDataIndex].type);
                                signatureBuilder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(handle));
                            }
                            break;

                            case EmbeddedSignatureDataKind.ArrayShape:
                                return;

                            default:
                                throw new NotImplementedException();
                            }

                            _embeddedDataIndex++;
                        }
                    }
                }
            }
        void SerializeDeltaLinesAndColumns(BlobBuilder writer, SequencePoint sequencePoint)
        {
            int deltaLines   = sequencePoint.EndLine - sequencePoint.StartLine;
            int deltaColumns = sequencePoint.EndColumn - sequencePoint.StartColumn;

            // only hidden sequence points have zero width
            if (!(deltaLines != 0 || deltaColumns != 0 || sequencePoint.IsHidden))
            {
                throw new InvalidOperationException("Only hidden sequence points have zero width ");
            }

            writer.WriteCompressedInteger(deltaLines);

            if (deltaLines == 0)
            {
                writer.WriteCompressedInteger(deltaColumns);
            }
            else
            {
                writer.WriteCompressedSignedInteger(deltaColumns);
            }
        }
Beispiel #17
0
        internal BlobBuilder BuildBlob(MethodDefinitionHandle moveNext)
        {
            BlobBuilder blob = new BlobBuilder();

            blob.WriteUInt32((uint)CatchHandlerOffset);
            foreach (var await in Awaits)
            {
                blob.WriteUInt32((uint)await.YieldOffset);
                blob.WriteUInt32((uint)await.ResumeOffset);
                blob.WriteCompressedInteger(MetadataTokens.GetToken(moveNext));
            }
            return(blob);
        }
        private static BlobHandle SerializeAsyncMethodSteppingInfo(MetadataBuilder metadataBuilder, ISymUnmanagedAsyncMethod symAsyncMethod, int moveNextMethodRowId)
        {
            var builder = new BlobBuilder();

            builder.WriteUInt32((uint)((long)symAsyncMethod.GetCatchHandlerILOffset() + 1));

            foreach (var stepInfo in symAsyncMethod.GetAsyncStepInfos())
            {
                builder.WriteInt32(stepInfo.YieldOffset);
                builder.WriteInt32(stepInfo.ResumeOffset);
                builder.WriteCompressedInteger(moveNextMethodRowId);
            }

            return(metadataBuilder.GetOrAddBlob(builder));
        }
Beispiel #19
0
        public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags))
        {
            _metadataBuilder  = new MetadataBuilder();
            _ilBuilder        = new BlobBuilder();
            _methodBodyStream = new MethodBodyStreamEncoder(_ilBuilder);
            StringHandle assemblyNameHandle = _metadataBuilder.GetOrAddString(assemblyName.Name);

            if (assemblyName.CultureName != null)
            {
                throw new ArgumentException("assemblyName");
            }

            if (assemblyName.GetPublicKeyToken() != null)
            {
                throw new ArgumentException("assemblyName");
            }

            var mvid = _metadataBuilder.ReserveGuid();

            _mvidFixup = mvid.Content;

            _metadataBuilder.AddModule(0, assemblyNameHandle, mvid.Handle, default(GuidHandle), default(GuidHandle));
            _metadataBuilder.AddAssembly(assemblyNameHandle, assemblyName.Version ?? new Version(0, 0, 0, 0), default(StringHandle), default(BlobHandle), flags, AssemblyHashAlgorithm.None);

            var canonAssemblyNameHandle = _metadataBuilder.GetOrAddString("System.Private.Canon");
            var canonAssemblyRef        = _metadataBuilder.AddAssemblyReference(canonAssemblyNameHandle, new Version(0, 0, 0, 0), default(StringHandle), default(BlobHandle), (AssemblyFlags)0, default(BlobHandle));
            var systemStringHandle      = _metadataBuilder.GetOrAddString("System");
            var canonStringHandle       = _metadataBuilder.GetOrAddString("__Canon");
            var canonTypeRef            = _metadataBuilder.AddTypeReference(canonAssemblyRef, systemStringHandle, canonStringHandle);

            _typeRefs.Add(context.CanonType, canonTypeRef);

            _metadataBuilder.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                _metadataBuilder.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            BlobBuilder noArgsNoReturnStaticMethodSig = new BlobBuilder();
            BlobEncoder signatureEncoder = new BlobEncoder(noArgsNoReturnStaticMethodSig);

            signatureEncoder.MethodSignature(SignatureCallingConvention.Default, 0, false);
            noArgsNoReturnStaticMethodSig.WriteCompressedInteger(0);
            noArgsNoReturnStaticMethodSig.WriteByte((byte)SignatureTypeCode.Void);
            _noArgsVoidReturnStaticMethodSigHandle = _metadataBuilder.GetOrAddBlob(noArgsNoReturnStaticMethodSig);
        }
        void EncodeMethodSignature(BlobBuilder signatureBuilder, MethodSignature sig, EmbeddedSignatureDataEmitter signatureDataEmitter)
        {
            signatureDataEmitter.Push();
            BlobEncoder signatureEncoder      = new BlobEncoder(signatureBuilder);
            int         genericParameterCount = sig.GenericParameterCount;
            bool        isInstanceMethod      = !sig.IsStatic;
            SignatureCallingConvention sigCallingConvention = SignatureCallingConvention.Default;

            switch (sig.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask)
            {
            case MethodSignatureFlags.CallingConventionVarargs:
                sigCallingConvention = SignatureCallingConvention.VarArgs;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionCdecl:
                sigCallingConvention = SignatureCallingConvention.CDecl;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionStdCall:
                sigCallingConvention = SignatureCallingConvention.StdCall;
                break;

            case MethodSignatureFlags.UnmanagedCallingConventionThisCall:
                sigCallingConvention = SignatureCallingConvention.ThisCall;
                break;

            case MethodSignatureFlags.UnmanagedCallingConvention:
                // [TODO] sigCallingConvention = SignatureCallingConvention.Unmanaged;
                sigCallingConvention = (SignatureCallingConvention)9;
                break;
            }

            signatureEncoder.MethodSignature(sigCallingConvention, genericParameterCount, isInstanceMethod);
            signatureBuilder.WriteCompressedInteger(sig.Length);
            EncodeType(signatureBuilder, sig.ReturnType, signatureDataEmitter);
            for (int i = 0; i < sig.Length; i++)
            {
                EncodeType(signatureBuilder, sig[i], signatureDataEmitter);
            }

            signatureDataEmitter.Pop();
        }
        private void SerializeAsyncMethodSteppingInfo(AsyncMoveNextBodyDebugInfo asyncInfo, MethodDefinitionHandle moveNextMethod)
        {
            Debug.Assert(asyncInfo.ResumeOffsets.Length == asyncInfo.YieldOffsets.Length);
            Debug.Assert(asyncInfo.CatchHandlerOffset >= -1);

            var writer = new BlobBuilder();

            writer.WriteUInt32((uint)((long)asyncInfo.CatchHandlerOffset + 1));

            for (int i = 0; i < asyncInfo.ResumeOffsets.Length; i++)
            {
                writer.WriteUInt32((uint)asyncInfo.YieldOffsets[i]);
                writer.WriteUInt32((uint)asyncInfo.ResumeOffsets[i]);
                writer.WriteCompressedInteger(MetadataTokens.GetRowNumber(moveNextMethod));
            }

            _debugMetadataOpt.AddCustomDebugInformation(
                parent: moveNextMethod,
                kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.AsyncMethodSteppingInformationBlob),
                value: _debugMetadataOpt.GetOrAddBlob(writer));
        }
Beispiel #22
0
        /// <summary>
        /// Creates the signature for a MethodSpec from the given type arguments.
        /// </summary>
        /// <param name="typeArguments">The signatures of the type arguments used to instantiate the method.</param>
        /// <returns>A byte array containing the binary MethodSpec signature.</returns>
        private static byte[] _createSignature(ReadOnlySpan <TypeSignature> typeArguments)
        {
            int typeArgsByteLength = 0;

            for (int i = 0; i < typeArguments.Length; i++)
            {
                typeArgsByteLength += typeArguments[i].byteLength;
            }

            if (typeArguments.Length <= 127 && typeArgsByteLength <= 254)
            {
                Span <byte> buffer = stackalloc byte[typeArgsByteLength + 2];
                buffer[0] = 0x0A;
                buffer[1] = (byte)typeArguments.Length;

                Span <byte> curSpan = buffer.Slice(2);
                for (int i = 0; i < typeArguments.Length; i++)
                {
                    typeArguments[i].writeToSpan(curSpan);
                    curSpan = curSpan.Slice(typeArguments[i].byteLength);
                }

                return(buffer.ToArray());
            }
            else
            {
                var blobBuilder = new BlobBuilder();

                blobBuilder.WriteByte(0x0A);
                blobBuilder.WriteCompressedInteger(typeArguments.Length);

                for (int i = 0; i < typeArguments.Length; i++)
                {
                    typeArguments[i].writeToBlobBuilder(blobBuilder);
                }

                return(blobBuilder.ToArray());
            }
        }
        private BlobHandle SerializeDocumentName(string name)
        {
            Debug.Assert(name != null);

            int c1 = Count(name, s_separator1[0]);
            int c2 = Count(name, s_separator2[0]);

            char[] separator = (c1 >= c2) ? s_separator1 : s_separator2;

            // Estimate 2 bytes per part, if the blob heap gets big we expand the builder once.
            var writer = new BlobBuilder(1 + Math.Max(c1, c2) * 2);

            writer.WriteByte((byte)separator[0]);

            // TODO: avoid allocations
            foreach (var part in name.Split(separator))
            {
                BlobHandle partIndex = GetOrAddBlob(ImmutableArray.Create(MetadataWriter.s_utf8Encoding.GetBytes(part)));
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(partIndex));
            }

            return(GetOrAddBlob(writer));
        }
        internal void SerializeLambdaMap(BlobBuilder writer)
        {
            Debug.Assert(this.MethodOrdinal >= -1);
            writer.WriteCompressedInteger(this.MethodOrdinal + 1);

            int syntaxOffsetBaseline = -1;

            foreach (ClosureDebugInfo info in this.Closures)
            {
                if (info.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = info.SyntaxOffset;
                }
            }

            foreach (LambdaDebugInfo info in this.Lambdas)
            {
                if (info.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = info.SyntaxOffset;
                }
            }

            writer.WriteCompressedInteger(-syntaxOffsetBaseline);
            writer.WriteCompressedInteger(this.Closures.Length);

            foreach (ClosureDebugInfo info in this.Closures)
            {
                writer.WriteCompressedInteger(info.SyntaxOffset - syntaxOffsetBaseline);
            }

            foreach (LambdaDebugInfo info in this.Lambdas)
            {
                Debug.Assert(info.ClosureOrdinal >= LambdaDebugInfo.MinClosureOrdinal);
                Debug.Assert(info.LambdaId.Generation == 0);

                writer.WriteCompressedInteger(info.SyntaxOffset - syntaxOffsetBaseline);
                writer.WriteCompressedInteger(info.ClosureOrdinal - LambdaDebugInfo.MinClosureOrdinal);
            }
        }
Beispiel #25
0
        // TODO: 
        // WriteBytes(byte*)
        // WriteBytes(stream)
        // WriteBytes(byte[])
        // WriteBytes(IA<byte>)
        // WriteReference

        private static void TestCompressedUnsignedInteger(byte[] expected, int value)
        {
            var writer = new BlobWriter(4);
            writer.WriteCompressedInteger(value);
            AssertEx.Equal(expected, writer.ToArray());

            var builder = new BlobBuilder();
            builder.WriteCompressedInteger(value);
            AssertEx.Equal(expected, builder.ToArray());
        }
        internal void SerializeLocalSlots(BlobBuilder writer)
        {
            int syntaxOffsetBaseline = -1;
            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                if (localSlot.Id.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = localSlot.Id.SyntaxOffset;
                }
            }

            if (syntaxOffsetBaseline != -1)
            {
                writer.WriteByte(SyntaxOffsetBaseline);
                writer.WriteCompressedInteger(-syntaxOffsetBaseline);
            }

            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                SynthesizedLocalKind kind = localSlot.SynthesizedKind;
                Debug.Assert(kind <= SynthesizedLocalKind.MaxValidValueForLocalVariableSerializedToDebugInformation);

                if (!kind.IsLongLived())
                {
                    writer.WriteByte(0);
                    continue;
                }

                byte b = (byte)(kind + 1);
                Debug.Assert((b & (1 << 7)) == 0);

                bool hasOrdinal = localSlot.Id.Ordinal > 0;

                if (hasOrdinal)
                {
                    b |= 1 << 7;
                }

                writer.WriteByte(b);
                writer.WriteCompressedInteger(localSlot.Id.SyntaxOffset - syntaxOffsetBaseline);

                if (hasOrdinal)
                {
                    writer.WriteCompressedInteger(localSlot.Id.Ordinal);
                }
            }
        }
        internal void SerializeLambdaMap(BlobBuilder writer)
        {
            Debug.Assert(this.MethodOrdinal >= -1);
            writer.WriteCompressedInteger(this.MethodOrdinal + 1);

            int syntaxOffsetBaseline = -1;
            foreach (ClosureDebugInfo info in this.Closures)
            {
                if (info.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = info.SyntaxOffset;
                }
            }

            foreach (LambdaDebugInfo info in this.Lambdas)
            {
                if (info.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = info.SyntaxOffset;
                }
            }

            writer.WriteCompressedInteger(-syntaxOffsetBaseline);
            writer.WriteCompressedInteger(this.Closures.Length);

            foreach (ClosureDebugInfo info in this.Closures)
            {
                writer.WriteCompressedInteger(info.SyntaxOffset - syntaxOffsetBaseline);
            }

            foreach (LambdaDebugInfo info in this.Lambdas)
            {
                Debug.Assert(info.ClosureOrdinal >= LambdaDebugInfo.MinClosureOrdinal);
                Debug.Assert(info.LambdaId.Generation == 0);

                writer.WriteCompressedInteger(info.SyntaxOffset - syntaxOffsetBaseline);
                writer.WriteCompressedInteger(info.ClosureOrdinal - LambdaDebugInfo.MinClosureOrdinal);
            }
        }
Beispiel #28
0
        private void EncodeType(BlobBuilder blobBuilder, TypeDesc type)
        {
            if (type.IsPrimitive)
            {
                SignatureTypeCode primitiveCode;
                switch (type.Category)
                {
                case TypeFlags.Void:
                    primitiveCode = SignatureTypeCode.Void;
                    break;

                case TypeFlags.Boolean:
                    primitiveCode = SignatureTypeCode.Boolean;
                    break;

                case TypeFlags.Char:
                    primitiveCode = SignatureTypeCode.Char;
                    break;

                case TypeFlags.SByte:
                    primitiveCode = SignatureTypeCode.SByte;
                    break;

                case TypeFlags.Byte:
                    primitiveCode = SignatureTypeCode.Byte;
                    break;

                case TypeFlags.Int16:
                    primitiveCode = SignatureTypeCode.Int16;
                    break;

                case TypeFlags.UInt16:
                    primitiveCode = SignatureTypeCode.UInt16;
                    break;

                case TypeFlags.Int32:
                    primitiveCode = SignatureTypeCode.Int32;
                    break;

                case TypeFlags.UInt32:
                    primitiveCode = SignatureTypeCode.UInt32;
                    break;

                case TypeFlags.Int64:
                    primitiveCode = SignatureTypeCode.Int64;
                    break;

                case TypeFlags.UInt64:
                    primitiveCode = SignatureTypeCode.UInt64;
                    break;

                case TypeFlags.IntPtr:
                    primitiveCode = SignatureTypeCode.IntPtr;
                    break;

                case TypeFlags.UIntPtr:
                    primitiveCode = SignatureTypeCode.UIntPtr;
                    break;

                case TypeFlags.Single:
                    primitiveCode = SignatureTypeCode.Single;
                    break;

                case TypeFlags.Double:
                    primitiveCode = SignatureTypeCode.Double;
                    break;

                default:
                    throw new Exception("Unknown primitive type");
                }

                blobBuilder.WriteByte((byte)primitiveCode);
            }
            else if (type.IsSzArray)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.SZArray);
                EncodeType(blobBuilder, type.GetParameterType());
            }
            else if (type.IsArray)
            {
                var arrayType = (ArrayType)type;
                blobBuilder.WriteByte((byte)SignatureTypeCode.Array);
                EncodeType(blobBuilder, type.GetParameterType());
                var shapeEncoder = new ArrayShapeEncoder(blobBuilder);
                // TODO Add support for non-standard array shapes
                shapeEncoder.Shape(arrayType.Rank, default(ImmutableArray <int>), default(ImmutableArray <int>));
            }
            else if (type.IsPointer)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Pointer);
                EncodeType(blobBuilder, type.GetParameterType());
            }
            else if (type.IsFunctionPointer)
            {
                FunctionPointerType fnptrType = (FunctionPointerType)type;
                EncodeMethodSignature(blobBuilder, fnptrType.Signature);
            }
            else if (type.IsByRef)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.ByReference);
                EncodeType(blobBuilder, type.GetParameterType());
            }
            else if (type.IsObject)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else if (type.IsString)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.String);
            }
            else if (type.IsWellKnownType(WellKnownType.TypedReference))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.TypedReference);
            }
            else if (type.IsWellKnownType(WellKnownType.Void))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Void);
            }
            else if (type is SignatureVariable)
            {
                SignatureVariable sigVar = (SignatureVariable)type;
                SignatureTypeCode code   = sigVar.IsMethodSignatureVariable ? SignatureTypeCode.GenericMethodParameter : SignatureTypeCode.GenericTypeParameter;
                blobBuilder.WriteByte((byte)code);
                blobBuilder.WriteCompressedInteger(sigVar.Index);
            }
            else if (type is InstantiatedType)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.GenericTypeInstance);
                EncodeType(blobBuilder, type.GetTypeDefinition());
                blobBuilder.WriteCompressedInteger(type.Instantiation.Length);
                foreach (var instantiationArg in type.Instantiation)
                {
                    EncodeType(blobBuilder, instantiationArg);
                }
            }
            else if (type is MetadataType)
            {
                var metadataType = (MetadataType)type;
                // Must be class or valuetype
                blobBuilder.WriteByte(type.IsValueType ? (byte)SignatureTypeKind.ValueType : (byte)SignatureTypeKind.Class);
                int codedIndex = CodedIndex.TypeDefOrRef(GetTypeRef(metadataType));
                blobBuilder.WriteCompressedInteger(codedIndex);
            }
            else
            {
                throw new Exception("Unexpected type");
            }
        }
        public UserStringHandle GetUserString(string str)
        {
            int index;

            if (!_userStrings.TryGetValue(str, out index))
            {
                Debug.Assert(!_streamsAreComplete);

                index = _userStringWriter.Position + _userStringHeapStartOffset;
                _userStrings.Add(str, index);
                _userStringWriter.WriteCompressedInteger(str.Length * 2 + 1);

                _userStringWriter.WriteUTF16(str);

                // Write out a trailing byte indicating if the string is really quite simple
                byte stringKind = 0;
                foreach (char ch in str)
                {
                    if (ch >= 0x7F)
                    {
                        stringKind = 1;
                    }
                    else
                    {
                        switch ((int)ch)
                        {
                        case 0x1:
                        case 0x2:
                        case 0x3:
                        case 0x4:
                        case 0x5:
                        case 0x6:
                        case 0x7:
                        case 0x8:
                        case 0xE:
                        case 0xF:
                        case 0x10:
                        case 0x11:
                        case 0x12:
                        case 0x13:
                        case 0x14:
                        case 0x15:
                        case 0x16:
                        case 0x17:
                        case 0x18:
                        case 0x19:
                        case 0x1A:
                        case 0x1B:
                        case 0x1C:
                        case 0x1D:
                        case 0x1E:
                        case 0x1F:
                        case 0x27:
                        case 0x2D:
                            stringKind = 1;
                            break;

                        default:
                            continue;
                        }
                    }

                    break;
                }

                _userStringWriter.WriteByte(stringKind);
            }

            return(MetadataTokens.UserStringHandle(index));
        }
        private static BlobHandle SerializeSequencePoints(
            MetadataBuilder metadataBuilder,
            int localSignatureRowId,
            ImmutableArray <SymUnmanagedSequencePoint> sequencePoints,
            Dictionary <string, DocumentHandle> documentIndex,
            out DocumentHandle singleDocumentHandle)
        {
            if (sequencePoints.Length == 0)
            {
                singleDocumentHandle = default(DocumentHandle);
                return(default(BlobHandle));
            }

            var writer = new BlobBuilder();

            int previousNonHiddenStartLine   = -1;
            int previousNonHiddenStartColumn = -1;

            // header:
            writer.WriteCompressedInteger(localSignatureRowId);

            DocumentHandle previousDocument = TryGetSingleDocument(sequencePoints, documentIndex);

            singleDocumentHandle = previousDocument;

            for (int i = 0; i < sequencePoints.Length; i++)
            {
                var currentDocument = documentIndex[sequencePoints[i].Document.GetName()];
                if (previousDocument != currentDocument)
                {
                    // optional document in header or document record:
                    if (!previousDocument.IsNil)
                    {
                        writer.WriteCompressedInteger(0);
                    }

                    writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(currentDocument));
                    previousDocument = currentDocument;
                }

                // delta IL offset:
                if (i > 0)
                {
                    writer.WriteCompressedInteger((sequencePoints[i].Offset - sequencePoints[i - 1].Offset));
                }
                else
                {
                    writer.WriteCompressedInteger(sequencePoints[i].Offset);
                }

                if (sequencePoints[i].IsHidden)
                {
                    writer.WriteInt16(0);
                    continue;
                }

                // Delta Lines & Columns:
                SerializeDeltaLinesAndColumns(writer, sequencePoints[i]);

                // delta Start Lines & Columns:
                if (previousNonHiddenStartLine < 0)
                {
                    Debug.Assert(previousNonHiddenStartColumn < 0);
                    writer.WriteCompressedInteger(sequencePoints[i].StartLine);
                    writer.WriteCompressedInteger(sequencePoints[i].StartColumn);
                }
                else
                {
                    writer.WriteCompressedSignedInteger(sequencePoints[i].StartLine - previousNonHiddenStartLine);
                    writer.WriteCompressedSignedInteger(sequencePoints[i].StartColumn - previousNonHiddenStartColumn);
                }

                previousNonHiddenStartLine   = sequencePoints[i].StartLine;
                previousNonHiddenStartColumn = sequencePoints[i].StartColumn;
            }

            return(metadataBuilder.GetOrAddBlob(writer));
        }
        public static ReadyToRunStandaloneMethodMetadata Compute(EcmaMethod wrappedMethod)
        {
            var metadataReader = wrappedMethod.MetadataReader;
            var _module        = wrappedMethod.Module;
            var rva            = wrappedMethod.MetadataReader.GetMethodDefinition(wrappedMethod.Handle).RelativeVirtualAddress;
            var _methodBody    = _module.PEReader.GetMethodBody(rva);

            byte[] _alternateILStream = _methodBody.GetILBytes();

            var exceptionRegions = _methodBody.ExceptionRegions;

            ILExceptionRegion[] _exceptionRegions;

            int length = exceptionRegions.Length;

            if (length == 0)
            {
                _exceptionRegions = Array.Empty <ILExceptionRegion>();
            }
            else
            {
                _exceptionRegions = new ILExceptionRegion[length];
                for (int i = 0; i < length; i++)
                {
                    var exceptionRegion = exceptionRegions[i];

                    _exceptionRegions[i] = new ILExceptionRegion(
                        (ILExceptionRegionKind)exceptionRegion.Kind, // assumes that ILExceptionRegionKind and ExceptionRegionKind enums are in sync
                        exceptionRegion.TryOffset,
                        exceptionRegion.TryLength,
                        exceptionRegion.HandlerOffset,
                        exceptionRegion.HandlerLength,
                        MetadataTokens.GetToken(exceptionRegion.CatchType),
                        exceptionRegion.FilterOffset);
                }
            }

            BlobReader localsBlob = default(BlobReader);

            if (!_methodBody.LocalSignature.IsNil)
            {
                localsBlob = wrappedMethod.MetadataReader.GetBlobReader(wrappedMethod.MetadataReader.GetStandaloneSignature(_methodBody.LocalSignature).Signature);
            }

            AlternativeTypeRefProvider alternateTypes = new AlternativeTypeRefProvider();
            EcmaSignatureEncoder <AlternativeTypeRefProvider> alternateEncoder = new EcmaSignatureEncoder <AlternativeTypeRefProvider>(alternateTypes);
            Dictionary <int, int> _alternateNonTokenStrings  = new Dictionary <int, int>();
            BlobBuilder           _alternateNonTypeRefStream = new BlobBuilder();
            BlobBuilder           _nonCodeAlternateBlob      = new BlobBuilder();

            {
                // Generate alternate stream for exceptions.
                _nonCodeAlternateBlob.WriteCompressedInteger(_exceptionRegions.Length);

                for (int i = 0; i < _exceptionRegions.Length; i++)
                {
                    var region = _exceptionRegions[i];
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.Kind);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.TryOffset);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.TryLength);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.HandlerOffset);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.HandlerLength);
                    if (region.Kind == ILExceptionRegionKind.Catch)
                    {
                        int alternateToken = GetAlternateStreamToken(region.ClassToken);
                        int encodedToken   = CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.EntityHandle(alternateToken));
                        _nonCodeAlternateBlob.WriteCompressedInteger(encodedToken);
                    }
                    else if (region.Kind == ILExceptionRegionKind.Filter)
                    {
                        _nonCodeAlternateBlob.WriteCompressedInteger(region.FilterOffset);
                    }
                }

                if (localsBlob.Length == 0)
                {
                    // No locals. Encode a 2 to indicate this
                    _nonCodeAlternateBlob.WriteByte(2);
                }
                else
                {
                    _nonCodeAlternateBlob.WriteByte(_methodBody.LocalVariablesInitialized ? (byte)1 : (byte)0);
                    EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(localsBlob, _nonCodeAlternateBlob, GetAlternateStreamToken);
                    sigTranslator.ParseLocalsSignature();
                }
            }

            ILTokenReplacer.Replace(_alternateILStream, GetAlternateStreamToken);

            // Add all the streams together into the _nonCodeAlternateBlob
            int expectedFinalSize = _nonCodeAlternateBlob.Count + _alternateILStream.Length + _alternateNonTypeRefStream.Count;

            _nonCodeAlternateBlob.WriteBytes(_alternateILStream);
            _nonCodeAlternateBlob.LinkSuffix(_alternateNonTypeRefStream);
            Debug.Assert(expectedFinalSize == _nonCodeAlternateBlob.Count);

            ReadyToRunStandaloneMethodMetadata methodBlock = new ReadyToRunStandaloneMethodMetadata();

            methodBlock.ConstantData = _nonCodeAlternateBlob.ToArray();
            methodBlock.TypeRefs     = alternateTypes._alternateTypeRefStream.ToArray();
            return(methodBlock);

            ///// HELPER FUNCTIONS

            unsafe int GetAlternateStreamToken(int token)
            {
                if (token == 0 || !_alternateNonTokenStrings.TryGetValue(token, out int alternateToken))
                {
                    var handle = MetadataTokens.Handle(token);

                    if (handle.Kind == HandleKind.TypeDefinition || handle.Kind == HandleKind.TypeReference)
                    {
                        EcmaType ecmaType = (EcmaType)wrappedMethod.Module.GetObject(MetadataTokens.EntityHandle(token));
                        alternateToken = MetadataTokens.GetToken(alternateTypes.GetTypeDefOrRefHandleForTypeDesc(ecmaType));
                    }
                    else
                    {
                        BlobBuilder blob = new BlobBuilder();
                        int         flag = 0;
                        if (handle.Kind == HandleKind.UserString)
                        {
                            string strAlternate = metadataReader.GetUserString((UserStringHandle)handle);
                            flag = 0x70000000;
                            blob.WriteCompressedInteger(strAlternate.Length);
                            fixed(char *charData = strAlternate)
                            {
                                blob.WriteBytes((byte *)charData, strAlternate.Length * 2);
                            }

                            // TODO: consider encoding via wtf-8, or possibly utf-8
                        }
                        else if (handle.Kind == HandleKind.TypeSpecification)
                        {
                            flag = 0x1B000000;
                            var sigBlob = metadataReader.GetBlobReader(metadataReader.GetTypeSpecification((TypeSpecificationHandle)handle).Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseType();
                        }
                        else if (handle.Kind == HandleKind.MemberReference)
                        {
                            flag = 0x0a000000;
                            var memberReference = metadataReader.GetMemberReference((MemberReferenceHandle)handle);
                            var sigBlob         = metadataReader.GetBlobReader(memberReference.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMemberRefSignature();
                            blob.WriteSerializedString(metadataReader.GetString(memberReference.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(memberReference.Parent)))));
                        }
                        else if (handle.Kind == HandleKind.MethodDefinition)
                        {
                            flag = 0x0a000000;
                            var methodDefinition = metadataReader.GetMethodDefinition((MethodDefinitionHandle)handle);
                            var sigBlob          = metadataReader.GetBlobReader(methodDefinition.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSignature();
                            blob.WriteSerializedString(metadataReader.GetString(methodDefinition.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(methodDefinition.GetDeclaringType())))));
                        }
                        else if (handle.Kind == HandleKind.FieldDefinition)
                        {
                            flag = 0x0a000000;
                            var fieldDefinition = metadataReader.GetFieldDefinition((FieldDefinitionHandle)handle);
                            var sigBlob         = metadataReader.GetBlobReader(fieldDefinition.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseFieldSignature();
                            blob.WriteSerializedString(metadataReader.GetString(fieldDefinition.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(fieldDefinition.GetDeclaringType())))));
                        }
                        else if (handle.Kind == HandleKind.MethodSpecification)
                        {
                            flag = 0x2B000000;
                            var methodSpecification = metadataReader.GetMethodSpecification((MethodSpecificationHandle)handle);
                            var sigBlob             = metadataReader.GetBlobReader(methodSpecification.Signature);
                            blob.WriteCompressedInteger(MetadataTokens.GetRowNumber(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(methodSpecification.Method)))));
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSpecSignature();
                        }
                        else if (handle.Kind == HandleKind.StandaloneSignature)
                        {
                            flag = 0x11000000;
                            var reader  = wrappedMethod.Module.MetadataReader;
                            var sigBlob = reader.GetBlobReader(reader.GetStandaloneSignature((StandaloneSignatureHandle)handle).Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSignature();
                        }

                        _alternateNonTypeRefStream.WriteBytes(blob.ToArray());
                        alternateToken = (_alternateNonTokenStrings.Count + 1) | flag;
                    }
                    _alternateNonTokenStrings.Add(token, alternateToken);
                }

                return(alternateToken);
            }
        }
        private void SerializeDeltaLinesAndColumns(BlobBuilder writer, SourceSpan span)
        {
            int deltaLines = span.EndLine - span.StartLine;
            int deltaColumns = span.EndColumn - span.StartColumn;

            // spans can't have zero width
            Debug.Assert(deltaLines != 0 || deltaColumns != 0);

            writer.WriteCompressedInteger(deltaLines);

            if (deltaLines == 0)
            {
                writer.WriteCompressedInteger(deltaColumns);
            }
            else
            {
                writer.WriteCompressedSignedInteger(deltaColumns);
            }
        }
        public unsafe static void Convert(BlobBuilder builder, MetadataModel metadataModel, byte[] signature, object value)
        {
            fixed(byte *sigPtr = signature)
            {
                var sigReader = new BlobReader(sigPtr, signature.Length);

                // copy custom modifiers over:
                byte rawTypeCode;

                while (true)
                {
                    rawTypeCode = sigReader.ReadByte();
                    if (rawTypeCode != (int)SignatureTypeCode.OptionalModifier && rawTypeCode != (int)SignatureTypeCode.RequiredModifier)
                    {
                        break;
                    }

                    builder.WriteByte(rawTypeCode);
                    builder.WriteCompressedInteger(sigReader.ReadCompressedInteger());
                }

                switch ((SignatureTypeCode)rawTypeCode)
                {
                case (SignatureTypeCode)SignatureTypeKind.Class:
                case (SignatureTypeCode)SignatureTypeKind.ValueType:
                    int typeRefDefSpec = sigReader.ReadCompressedInteger();

                    if (value is decimal)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <decimal>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDecimal((decimal)value);
                    }
                    else if (value is DateTime)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <date-time>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDateTime((DateTime)value);
                    }
                    else if (value == null)
                    {
                        // GeneralConstant: CLASS TypeDefOrRefOrSpecEncoded
                        builder.WriteByte(rawTypeCode);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }
                    else
                    {
                        // EnumConstant ::= EnumTypeCode EnumValue EnumType
                        // EnumTypeCode ::= BOOLEAN | CHAR | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8
                        // EnumType     ::= TypeDefOrRefOrSpecEncoded

                        var enumTypeCode = MetadataHelpers.GetConstantTypeCode(value);
                        builder.WriteByte((byte)enumTypeCode);
                        builder.WriteConstant(value);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }

                    break;

                case SignatureTypeCode.Object:
                    // null:
                    Debug.Assert(value == null);
                    builder.WriteByte((byte)SignatureTypeCode.Object);
                    break;

                case SignatureTypeCode.Boolean:
                case SignatureTypeCode.Char:
                case SignatureTypeCode.SByte:
                case SignatureTypeCode.Byte:
                case SignatureTypeCode.Int16:
                case SignatureTypeCode.UInt16:
                case SignatureTypeCode.Int32:
                case SignatureTypeCode.UInt32:
                case SignatureTypeCode.Int64:
                case SignatureTypeCode.UInt64:
                case SignatureTypeCode.Single:
                case SignatureTypeCode.Double:
                case SignatureTypeCode.String:
                    // PrimitiveConstant
                    builder.WriteByte(rawTypeCode);
                    builder.WriteConstant(value);
                    break;

                case SignatureTypeCode.SZArray:
                case SignatureTypeCode.Array:
                case SignatureTypeCode.GenericTypeInstance:
                    Debug.Assert(value == null);

                    // Find an existing TypeSpec in metadata.
                    // If there isn't one we can't represent the constant type in the Portable PDB, use Object.

                    // +1/-1 for the type code we already read.
                    var spec = new byte[sigReader.RemainingBytes + 1];
                    Buffer.BlockCopy(signature, sigReader.Offset - 1, spec, 0, spec.Length);

                    TypeSpecificationHandle typeSpec;
                    if (metadataModel.TryResolveTypeSpecification(spec, out typeSpec))
                    {
                        builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(typeSpec));
                    }
                    else
                    {
                        // TODO: warning - can't translate const type
                        builder.WriteByte((byte)SignatureTypeCode.Object);
                    }

                    break;

                case SignatureTypeCode.GenericMethodParameter:
                case SignatureTypeCode.GenericTypeParameter:
                case SignatureTypeCode.FunctionPointer:
                case SignatureTypeCode.Pointer:
                    // generic parameters, pointers are not valid types for constants:
                    throw new BadImageFormatException();
                }
            }
        }
        private BlobHandle SerializeDocumentName(string name)
        {
            Debug.Assert(name != null);

            int c1 = Count(name, s_separator1[0]);
            int c2 = Count(name, s_separator2[0]);
            char[] separator = (c1 >= c2) ? s_separator1 : s_separator2;

            // Estimate 2 bytes per part, if the blob heap gets big we expand the builder once.
            var writer = new BlobBuilder(1 + Math.Max(c1, c2) * 2);

            writer.WriteByte((byte)separator[0]);

            // TODO: avoid allocations
            foreach (var part in name.Split(separator))
            {
                BlobHandle partIndex = GetOrAddBlob(ImmutableArray.Create(MetadataWriter.s_utf8Encoding.GetBytes(part)));
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(partIndex));
            }

            return GetOrAddBlob(writer);
        }
        private BlobHandle SerializeSpans(
            ImmutableArray<SourceSpan> spans,
            Dictionary<DebugSourceDocument, int> documentIndex)
        {
            if (spans.Length == 0)
            {
                return default(BlobHandle);
            }

            // 4 bytes per span plus a header, the builder expands by the same amount.
            var writer = new BlobBuilder(4 + spans.Length * 4);

            int previousStartLine = -1;
            int previousStartColumn = -1;
            DebugSourceDocument previousDocument = spans[0].Document;

            // header:
            writer.WriteCompressedInteger(GetOrAddDocument(previousDocument, documentIndex));

            for (int i = 0; i < spans.Length; i++)
            {
                var currentDocument = spans[i].Document;
                if (previousDocument != currentDocument)
                {
                    writer.WriteInt16(0);
                    writer.WriteCompressedInteger(GetOrAddDocument(currentDocument, documentIndex));
                    previousDocument = currentDocument;
                }

                // Delta Lines & Columns:
                SerializeDeltaLinesAndColumns(writer, spans[i]);

                // delta Start Lines & Columns:
                if (previousStartLine < 0)
                {
                    Debug.Assert(previousStartColumn < 0);
                    writer.WriteCompressedInteger(spans[i].StartLine);
                    writer.WriteCompressedInteger(spans[i].StartColumn);
                }
                else
                {
                    writer.WriteCompressedSignedInteger(spans[i].StartLine - previousStartLine);
                    writer.WriteCompressedSignedInteger(spans[i].StartColumn - previousStartColumn);
                }

                previousStartLine = spans[i].StartLine;
                previousStartColumn = spans[i].StartColumn;
            }

            return GetOrAddBlob(writer);
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // This node does not trigger generation of other nodes.
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            ObjectDataBuilder objDataBuilder = new ObjectDataBuilder(factory, relocsOnly);

            // Emit number of dictionaries in table
            objDataBuilder.AddSymbol(this);
            IReadOnlyCollection <GenericDictionaryNode> dictionariesEmitted = factory.MetadataManager.GetCompiledGenericDictionaries();

            objDataBuilder.EmitInt(dictionariesEmitted.Count);
            DebugInfoBlob signatureData = new DebugInfoBlob();

            BlobBuilder          signatureBlobBuilder = new BlobBuilder();
            BlobBuilder          signatureLenBuilder  = new BlobBuilder();
            ManagedBinaryEmitter pseudoAssembly       = factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly;

            foreach (GenericDictionaryNode dictionary in dictionariesEmitted)
            {
                objDataBuilder.EmitReloc(dictionary, RelocType.IMAGE_REL_BASED_ADDR32NB);
                objDataBuilder.EmitUInt(signatureData.Size());

                signatureBlobBuilder.Clear();

                int typeDictLen   = dictionary.TypeInstantiation.IsNull ? 0 : dictionary.TypeInstantiation.Length;
                int methodDictLen = dictionary.MethodInstantiation.IsNull ? 0 : dictionary.MethodInstantiation.Length;
                signatureBlobBuilder.WriteCompressedInteger(typeDictLen + methodDictLen);

                if (typeDictLen != 0)
                {
                    foreach (TypeDesc type in dictionary.TypeInstantiation)
                    {
                        pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
                    }
                }

                if (methodDictLen != 0)
                {
                    foreach (TypeDesc type in dictionary.MethodInstantiation)
                    {
                        pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
                    }
                }

                int blobSize = signatureBlobBuilder.Count;

                signatureLenBuilder.Clear();
                signatureLenBuilder.WriteCompressedInteger(blobSize);

                // Prepend the signature data with a length
                signatureData.WriteBuffer(signatureLenBuilder);
                // And then attach the actual signature data
                signatureData.WriteBuffer(signatureBlobBuilder);
            }

            // Attach signature information to end after all of the rva/offset pairs
            objDataBuilder.EmitBytes(signatureData.ToArray());

            return(objDataBuilder.ToObjectData());
        }
Beispiel #37
0
        public void CompressUnsignedIntegersFromSpecExamples()
        {
            // These examples are straight from the CLI spec.

            TestCompressedUnsignedInteger(new byte[] { 0x00 }, 0);
            TestCompressedUnsignedInteger(new byte[] { 0x03 }, 0x03);
            TestCompressedUnsignedInteger(new byte[] { 0x7f }, 0x7F);
            TestCompressedUnsignedInteger(new byte[] { 0x80, 0x80 }, 0x80);
            TestCompressedUnsignedInteger(new byte[] { 0xAE, 0x57 }, 0x2E57);
            TestCompressedUnsignedInteger(new byte[] { 0xBF, 0xFF }, 0x3FFF);
            TestCompressedUnsignedInteger(new byte[] { 0xC0, 0x00, 0x40, 0x00 }, 0x4000);
            TestCompressedUnsignedInteger(new byte[] { 0xDF, 0xFF, 0xFF, 0xFF }, 0x1FFFFFFF);

            var writer = new BlobWriter(4);
            var builder = new BlobBuilder();

            Assert.Throws<ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(-1));
            Assert.Throws<ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(-1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1));
        }