private void SerializeNamespaceScopeMetadata(ref CustomDebugInfoEncoder encoder, EmitContext context, IMethodBody methodBody) { if (context.Module.GenerateVisualBasicStylePdb) { return; } if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody)) { Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody)); encoder.AddForwardMethodInfo(_previousMethodWithUsingInfo); return; } var usingCounts = ArrayBuilder <int> .GetInstance(); for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent) { usingCounts.Add(scope.GetUsedNamespaces().Length); } encoder.AddUsingGroups(usingCounts); usingCounts.Free(); if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody)) { encoder.AddForwardModuleInfo(_methodWithModuleInfo); } }
public CompilerContext(IScriptScope scriptScope, ITypeScope typeScope, IImportScope importScope, CompilerOptions options) { this.m_scriptScope = scriptScope; this.m_typeScope = typeScope; this.m_importScope = importScope; this.m_options = options; }
protected override void ProcessMethodBody(IMethodDefinition method) { if (method.HasBody() && !metadataWriter.MetadataOnly) { var body = method.GetBody(Context); if (body != null) { this.Visit(body); for (IImportScope scope = body.ImportScope; scope != null; scope = scope.Parent) { if (_alreadySeenScopes.Add(scope)) { VisitImports(scope.GetUsedNamespaces()); } else { break; } } } else if (!metadataWriter.MetadataOnly) { throw ExceptionUtilities.Unreachable; } } }
private ImportScopeHandle GetImportScopeIndex( IImportScope scope, Dictionary <IImportScope, ImportScopeHandle> scopeIndex ) { ImportScopeHandle scopeHandle; if (scopeIndex.TryGetValue(scope, out scopeHandle)) { // scope is already indexed: return(scopeHandle); } var parent = scope.Parent; var parentScopeHandle = (parent != null) ? GetImportScopeIndex(scope.Parent, scopeIndex) : ModuleImportScopeHandle; var result = _debugMetadataOpt.AddImportScope( parentScope: parentScopeHandle, imports: SerializeImportsBlob(scope) ); scopeIndex.Add(scope, result); return(result); }
private BlobHandle SerializeImportsBlob(IImportScope scope) { var writer = new BlobBuilder(); foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces()) { SerializeImport(writer, import); } return(_debugMetadataOpt.GetOrAddBlob(writer)); }
private BlobIdx SerializeImportsBlob(IImportScope scope) { var writer = new BlobBuilder(); foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces()) { SerializeImport(writer, import); } return(_debugHeapsOpt.GetBlobIndex(writer)); }
private static IImportScope GetLastScope(IImportScope scope) { while (true) { var parent = scope.Parent; if (parent == null) { return(scope); } scope = parent; } }
private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody methodBody, ArrayBuilder <MemoryStream> customDebugInfo) { if (context.Module.GenerateVisualBasicStylePdb) { return; } if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody)) { Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody)); SerializeReferenceToPreviousMethodWithUsingInfo(customDebugInfo); return; } MemoryStream customMetadata = new MemoryStream(); List <ushort> usingCounts = new List <ushort>(); BinaryWriter cmw = new BinaryWriter(customMetadata); for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent) { usingCounts.Add((ushort)scope.GetUsedNamespaces().Length); } // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the // case where usingCounts was empty, but I'm not sure why. if (usingCounts.Count > 0) { uint streamLength; cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindUsingInfo); cmw.Align(4); cmw.WriteUint(streamLength = BitArithmeticUtilities.Align((uint)usingCounts.Count * 2 + 10, 4)); cmw.WriteUshort((ushort)usingCounts.Count); foreach (ushort uc in usingCounts) { cmw.WriteUshort(uc); } cmw.Align(4); Debug.Assert(streamLength == customMetadata.Length); customDebugInfo.Add(customMetadata); } if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody)) { SerializeReferenceToMethodWithModuleInfo(customDebugInfo); } }
private bool ShouldForwardToPreviousMethodWithUsingInfo(EmitContext context, IMethodBody methodBody) { if (_previousMethodBodyWithUsingInfo == null || ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody)) { return(false); } // VB includes method namespace in namespace scopes: if (context.Module.GenerateVisualBasicStylePdb) { if (_pdbWriter.GetOrCreateSerializedNamespaceName(_previousMethodBodyWithUsingInfo.MethodDefinition.ContainingNamespace) != _pdbWriter.GetOrCreateSerializedNamespaceName(methodBody.MethodDefinition.ContainingNamespace)) { return(false); } } IImportScope previousScopes = _previousMethodBodyWithUsingInfo.ImportScope; // methods share the same import scope (common case for methods declared in the same file) if (methodBody.ImportScope == previousScopes) { return(true); } // If methods are in different files they don't share the same scopes, // but the imports might be the same nevertheless. // Note: not comparing project-level imports since those are the same for all method bodies. IImportScope s1 = methodBody.ImportScope; IImportScope s2 = previousScopes; while (s1 != null && s2 != null) { if (!s1.GetUsedNamespaces().SequenceEqual(s2.GetUsedNamespaces())) { return(false); } s1 = s1.Parent; s2 = s2.Parent; } return(s1 == s2); }
private int GetImportScopeIndex(IImportScope scope, Dictionary <IImportScope, int> scopeIndex) { int scopeRid; if (scopeIndex.TryGetValue(scope, out scopeRid)) { // scope is already indexed: return(scopeRid); } var parent = scope.Parent; int parentScopeRid = (parent != null) ? GetImportScopeIndex(scope.Parent, scopeIndex) : ModuleImportScopeRid; _importScopeTable.Add(new ImportScopeRow { Parent = (uint)parentScopeRid, Imports = SerializeImportsBlob(scope) }); var rid = _importScopeTable.Count; scopeIndex.Add(scope, rid); return(rid); }
private void DefineNamespaceScopes(IMethodBody methodBody) { var module = Module; bool isVisualBasic = module.GenerateVisualBasicStylePdb; IMethodDefinition method = methodBody.MethodDefinition; var namespaceScopes = methodBody.ImportScope; // NOTE: All extern aliases are stored on the outermost namespace scope. PooledHashSet <string> lazyDeclaredExternAliases = null; if (!isVisualBasic) { foreach (var import in GetLastScope(namespaceScopes).GetUsedNamespaces(Context)) { if (import.TargetNamespaceOpt == null && import.TargetTypeOpt == null) { Debug.Assert(import.AliasOpt != null); Debug.Assert(import.TargetAssemblyOpt == null); if (lazyDeclaredExternAliases == null) { lazyDeclaredExternAliases = PooledHashSet <string> .GetInstance(); } lazyDeclaredExternAliases.Add(import.AliasOpt); } } } // file and namespace level for (IImportScope scope = namespaceScopes; scope != null; scope = scope.Parent) { foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces(Context)) { var importString = TryEncodeImport(import, lazyDeclaredExternAliases, isProjectLevel: false); if (importString != null) { UsingNamespace(importString, method); } } } lazyDeclaredExternAliases?.Free(); // project level if (isVisualBasic) { string defaultNamespace = module.DefaultNamespace; if (defaultNamespace != null) { // VB marks the default/root namespace with an asterisk UsingNamespace("*" + defaultNamespace, module); } foreach (string assemblyName in module.LinkedAssembliesDebugInfo) { UsingNamespace("&" + assemblyName, module); } foreach (UsedNamespaceOrType import in module.GetImports(Context)) { var importString = TryEncodeImport(import, null, isProjectLevel: true); if (importString != null) { UsingNamespace(importString, method); } } // VB current namespace -- VB appends the namespace of the container without prefixes UsingNamespace(GetOrCreateSerializedNamespaceName(method.ContainingNamespace), method); } }
private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, StandaloneSignatureHandle localSignatureHandleOpt, ref LocalVariableHandle lastLocalVariableHandle, ref LocalConstantHandle lastLocalConstantHandle) { if (bodyOpt == null) { _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle)); return; } bool isIterator = bodyOpt.StateMachineTypeName != null; bool emitDebugInfo = isIterator || bodyOpt.HasAnySequencePoints; if (!emitDebugInfo) { _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle)); return; } MethodDefinitionHandle methodHandle = MetadataTokens.MethodDefinitionHandle(methodRid); IImportScope bodyImportScope = bodyOpt.ImportScope; ImportScopeHandle importScopeHandle = (bodyImportScope != null) ? GetImportScopeIndex(bodyImportScope, _scopeIndex) : default(ImportScopeHandle); // documents & sequence points: ArrayBuilder <Cci.SequencePoint> sequencePoints = ArrayBuilder <Cci.SequencePoint> .GetInstance(); bodyOpt.GetSequencePoints(sequencePoints); BlobHandle sequencePointsBlob = SerializeSequencePoints(localSignatureHandleOpt, sequencePoints.ToImmutableAndFree(), _documentIndex, out DocumentHandle singleDocumentHandle); _debugMetadataOpt.AddMethodDebugInformation(document: singleDocumentHandle, sequencePoints: sequencePointsBlob); // Unlike native PDB we don't emit an empty root scope. // scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first). if (bodyOpt.LocalScopes.Length == 0) { // TODO: the compiler should produce a scope for each debuggable method _debugMetadataOpt.AddLocalScope( method: methodHandle, importScope: importScopeHandle, variableList: NextHandle(lastLocalVariableHandle), constantList: NextHandle(lastLocalConstantHandle), startOffset: 0, length: bodyOpt.IL.Length); } else { foreach (LocalScope scope in bodyOpt.LocalScopes) { _debugMetadataOpt.AddLocalScope( method: methodHandle, importScope: importScopeHandle, variableList: NextHandle(lastLocalVariableHandle), constantList: NextHandle(lastLocalConstantHandle), startOffset: scope.StartOffset, length: scope.Length); foreach (ILocalDefinition local in scope.Variables) { Debug.Assert(local.SlotIndex >= 0); lastLocalVariableHandle = _debugMetadataOpt.AddLocalVariable( attributes: local.PdbAttributes, index: local.SlotIndex, name: _debugMetadataOpt.GetOrAddString(local.Name)); SerializeLocalInfo(local, lastLocalVariableHandle); } foreach (ILocalDefinition constant in scope.Constants) { CodeAnalysis.CodeGen.MetadataConstant mdConstant = constant.CompileTimeValue; Debug.Assert(mdConstant != null); lastLocalConstantHandle = _debugMetadataOpt.AddLocalConstant( name: _debugMetadataOpt.GetOrAddString(constant.Name), signature: SerializeLocalConstantSignature(constant)); SerializeLocalInfo(constant, lastLocalConstantHandle); } } } AsyncMethodBodyDebugInfo asyncDebugInfo = bodyOpt.AsyncDebugInfo; if (asyncDebugInfo != null) { _debugMetadataOpt.AddStateMachineMethod( moveNextMethod: methodHandle, kickoffMethod: GetMethodDefinitionHandle(asyncDebugInfo.KickoffMethod)); SerializeAsyncMethodSteppingInfo(asyncDebugInfo, methodHandle); } SerializeStateMachineLocalScopes(bodyOpt, methodHandle); // delta doesn't need this information - we use information recorded by previous generation emit if (Context.Module.CommonCompilation.Options.EnableEditAndContinue && IsFullMetadata) { SerializeEncMethodDebugInformation(bodyOpt, methodHandle); } }
private IImportScope GetLastScope(IImportScope scope) { while (true) { var parent = scope.Parent; if (parent == null) { return scope; } scope = parent; } }