예제 #1
0
        public void SerializeDebugInfo(IMethodBody methodBody, uint localSignatureToken, CustomDebugInfoWriter customDebugInfoWriter)
        {
            Debug.Assert(_metadataWriter != null);

            bool isIterator    = methodBody.StateMachineTypeName != null;
            bool emitDebugInfo = isIterator || methodBody.HasAnySequencePoints;

            if (!emitDebugInfo)
            {
                return;
            }

            uint methodToken = _metadataWriter.GetMethodToken(methodBody.MethodDefinition);

            OpenMethod(methodToken);

            var localScopes = methodBody.LocalScopes;

            // CCI originally didn't have the notion of the default scope that is open
            // when a method is opened. In order to reproduce CSC PDBs, this must be added. Otherwise
            // a seemingly unnecessary scope that contains only other scopes is put in the PDB.
            if (localScopes.Length > 0)
            {
                this.DefineScopeLocals(localScopes[0], localSignatureToken);
            }

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            if (!isIterator)
            {
                IMethodDefinition forwardToMethod;
                if (customDebugInfoWriter.ShouldForwardNamespaceScopes(Context, methodBody, methodToken, out forwardToMethod))
                {
                    if (forwardToMethod != null)
                    {
                        UsingNamespace("@" + _metadataWriter.GetMethodToken(forwardToMethod), methodBody.MethodDefinition);
                    }
                    // otherwise, the forwarding is done via custom debug info
                }
                else
                {
                    this.DefineNamespaceScopes(methodBody);
                }
            }

            DefineLocalScopes(localScopes, localSignatureToken);

            EmitSequencePoints(methodBody.GetSequencePoints());

            AsyncMethodBodyDebugInfo asyncDebugInfo = methodBody.AsyncDebugInfo;

            if (asyncDebugInfo != null)
            {
                SetAsyncInfo(
                    methodToken,
                    _metadataWriter.GetMethodToken(asyncDebugInfo.KickoffMethod),
                    asyncDebugInfo.CatchHandlerOffset,
                    asyncDebugInfo.YieldOffsets,
                    asyncDebugInfo.ResumeOffsets);
            }

            var compilationOptions = Context.ModuleBuilder.CommonCompilation.Options;

            // We need to avoid emitting CDI DynamicLocals = 5 and EditAndContinueLocalSlotMap = 6 for files processed by WinMDExp until
            // bug #1067635 is fixed and available in SDK.
            bool suppressNewCustomDebugInfo = !compilationOptions.ExtendedCustomDebugInformation ||
                                              (compilationOptions.OutputKind == OutputKind.WindowsRuntimeMetadata);

            bool emitEncInfo = compilationOptions.EnableEditAndContinue && !_metadataWriter.IsFullMetadata;

            bool emitExternNamespaces;

            byte[] blob = customDebugInfoWriter.SerializeMethodDebugInfo(Context, methodBody, methodToken, emitEncInfo, suppressNewCustomDebugInfo, out emitExternNamespaces);
            if (blob != null)
            {
                DefineCustomMetadata("MD2", blob);
            }

            if (emitExternNamespaces)
            {
                this.DefineAssemblyReferenceAliases();
            }

            // TODO: it's not clear why we are closing a scope here with IL length:
            CloseScope(methodBody.IL.Length);

            CloseMethod();
        }