/// <summary> /// Create a SequencePointList with the raw sequence points from an ArrayBuilder. /// A linked list of instances for each syntax tree is created (almost always of length one). /// </summary> public static SequencePointList Create(ArrayBuilder<RawSequencePoint> seqPointBuilder, ILBuilder builder) { if (seqPointBuilder.Count == 0) { return SequencePointList.s_empty; } SequencePointList first = null, current = null; int totalPoints = seqPointBuilder.Count; int last = 0; for (int i = 1; i <= totalPoints; ++i) { if (i == totalPoints || seqPointBuilder[i].SyntaxTree != seqPointBuilder[i - 1].SyntaxTree) { // Create a new list SequencePointList next = new SequencePointList(seqPointBuilder[i - 1].SyntaxTree, GetSubArray(seqPointBuilder, last, i - last, builder)); last = i; // Link together with any additional. if (current == null) { first = current = next; } else { current._next = next; current = next; } } } return first; }
public MethodBody( byte[] ilBits, ushort maxStack, Cci.IMethodDefinition parent, ImmutableArray <Cci.ILocalDefinition> locals, SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider, ImmutableArray <Cci.ExceptionHandlerRegion> exceptionHandlers, ImmutableArray <Cci.LocalScope> localScopes, Cci.CustomDebugInfoKind customDebugInfoKind, bool hasDynamicLocalVariables, ImmutableArray <Cci.NamespaceScope> namespaceScopes = default(ImmutableArray <Cci.NamespaceScope>), string iteratorClassName = null, ImmutableArray <Cci.LocalScope> iteratorScopes = default(ImmutableArray <Cci.LocalScope>), Cci.AsyncMethodBodyDebugInfo asyncMethodDebugInfo = null) { Debug.Assert(!locals.IsDefault); Debug.Assert(!exceptionHandlers.IsDefault); Debug.Assert(!localScopes.IsDefault); this.ilBits = ilBits; this.asyncMethodDebugInfo = asyncMethodDebugInfo; this.maxStack = maxStack; this.parent = parent; this.locals = locals; this.sequencePoints = sequencePoints; this.debugDocumentProvider = debugDocumentProvider; this.exceptionHandlers = exceptionHandlers; this.localScopes = localScopes; this.customDebugInfoKind = customDebugInfoKind; this.hasDynamicLocalVariables = hasDynamicLocalVariables; this.namespaceScopes = namespaceScopes.IsDefault ? ImmutableArray <Cci.NamespaceScope> .Empty : namespaceScopes; this.iteratorClassName = iteratorClassName; this.iteratorScopes = iteratorScopes.IsDefault ? ImmutableArray <Cci.LocalScope> .Empty : iteratorScopes; }
private FileLinePositionSpan?FindFirstRealSequencePoint() { SequencePointList current = this; while (current != null) { foreach (var offsetAndSpan in current._points) { TextSpan span = offsetAndSpan.Span; bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; if (!isHidden) { FileLinePositionSpan fileLinePositionSpan = current._tree.GetMappedLineSpanAndVisibility(span, out isHidden); if (!isHidden) { return(fileLinePositionSpan); } } } current = current._next; } return(null); }
/// <summary> /// Create a SequencePointList with the raw sequence points from an ArrayBuilder. /// A linked list of instances for each syntax tree is created (almost always of length one). /// </summary> public static SequencePointList Create(ArrayBuilder <RawSequencePoint> seqPointBuilder, ILBuilder builder) { if (seqPointBuilder.Count == 0) { return(SequencePointList.s_empty); } SequencePointList first = null, current = null; int totalPoints = seqPointBuilder.Count; int last = 0; for (int i = 1; i <= totalPoints; ++i) { if (i == totalPoints || seqPointBuilder[i].SyntaxTree != seqPointBuilder[i - 1].SyntaxTree) { // Create a new list SequencePointList next = new SequencePointList(seqPointBuilder[i - 1].SyntaxTree, GetSubArray(seqPointBuilder, last, i - last, builder)); last = i; // Link together with any additional. if (current == null) { first = current = next; } else { current._next = next; current = next; } } } return(first); }
public MethodBody( byte[] ilBits, ushort maxStack, Cci.IMethodDefinition parent, ImmutableArray<Cci.ILocalDefinition> locals, SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider, ImmutableArray<Cci.ExceptionHandlerRegion> exceptionHandlers, ImmutableArray<Cci.LocalScope> localScopes, Cci.CustomDebugInfoKind customDebugInfoKind, bool hasDynamicLocalVariables, ImmutableArray<Cci.NamespaceScope> namespaceScopes = default(ImmutableArray<Cci.NamespaceScope>), string iteratorClassName = null, ImmutableArray<Cci.LocalScope> iteratorScopes = default(ImmutableArray<Cci.LocalScope>), Cci.AsyncMethodBodyDebugInfo asyncMethodDebugInfo = null) { Debug.Assert(!locals.IsDefault); Debug.Assert(!exceptionHandlers.IsDefault); Debug.Assert(!localScopes.IsDefault); this.ilBits = ilBits; this.asyncMethodDebugInfo = asyncMethodDebugInfo; this.maxStack = maxStack; this.parent = parent; this.locals = locals; this.sequencePoints = sequencePoints; this.debugDocumentProvider = debugDocumentProvider; this.exceptionHandlers = exceptionHandlers; this.localScopes = localScopes; this.customDebugInfoKind = customDebugInfoKind; this.hasDynamicLocalVariables = hasDynamicLocalVariables; this.namespaceScopes = namespaceScopes.IsDefault ? ImmutableArray<Cci.NamespaceScope>.Empty : namespaceScopes; this.iteratorClassName = iteratorClassName; this.iteratorScopes = iteratorScopes.IsDefault ? ImmutableArray<Cci.LocalScope>.Empty : iteratorScopes; }
private static ImmutableArray <Cci.SequencePoint> GetSequencePoints(SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider) { if (sequencePoints == null || sequencePoints.IsEmpty) { return(ImmutableArray <Cci.SequencePoint> .Empty); } var sequencePointsBuilder = ArrayBuilder <Cci.SequencePoint> .GetInstance(); sequencePoints.GetSequencePoints(debugDocumentProvider, sequencePointsBuilder); return(sequencePointsBuilder.ToImmutableAndFree()); }
public MethodBody( ImmutableArray <byte> ilBits, ushort maxStack, Cci.IMethodDefinition parent, DebugId methodId, ImmutableArray <Cci.ILocalDefinition> locals, SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider, ImmutableArray <Cci.ExceptionHandlerRegion> exceptionHandlers, bool areLocalsZeroed, bool hasStackalloc, ImmutableArray <Cci.LocalScope> localScopes, bool hasDynamicLocalVariables, Cci.IImportScope importScopeOpt, ImmutableArray <LambdaDebugInfo> lambdaDebugInfo, ImmutableArray <ClosureDebugInfo> closureDebugInfo, string stateMachineTypeNameOpt, ImmutableArray <StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes, ImmutableArray <EncHoistedLocalInfo> stateMachineHoistedLocalSlots, ImmutableArray <Cci.ITypeReference?> stateMachineAwaiterSlots, StateMachineStatesDebugInfo stateMachineStatesDebugInfo, StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfoOpt, DynamicAnalysisMethodBodyData dynamicAnalysisDataOpt) { Debug.Assert(!locals.IsDefault); Debug.Assert(!exceptionHandlers.IsDefault); Debug.Assert(!localScopes.IsDefault); _ilBits = ilBits; _maxStack = maxStack; _parent = parent; _methodId = methodId; _locals = locals; _exceptionHandlers = exceptionHandlers; _areLocalsZeroed = areLocalsZeroed; HasStackalloc = hasStackalloc; _localScopes = localScopes; _hasDynamicLocalVariables = hasDynamicLocalVariables; _importScopeOpt = importScopeOpt; _lambdaDebugInfo = lambdaDebugInfo; _closureDebugInfo = closureDebugInfo; _stateMachineTypeNameOpt = stateMachineTypeNameOpt; _stateMachineHoistedLocalScopes = stateMachineHoistedLocalScopes; _stateMachineHoistedLocalSlots = stateMachineHoistedLocalSlots; _stateMachineAwaiterSlots = stateMachineAwaiterSlots; _stateMachineStatesDebugInfo = stateMachineStatesDebugInfo; _stateMachineMoveNextDebugInfoOpt = stateMachineMoveNextDebugInfoOpt; _dynamicAnalysisDataOpt = dynamicAnalysisDataOpt; _sequencePoints = GetSequencePoints(sequencePoints, debugDocumentProvider); }
public MethodBody( ImmutableArray<byte> ilBits, ushort maxStack, Cci.IMethodDefinition parent, DebugId methodId, ImmutableArray<Cci.ILocalDefinition> locals, SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider, ImmutableArray<Cci.ExceptionHandlerRegion> exceptionHandlers, ImmutableArray<Cci.LocalScope> localScopes, bool hasDynamicLocalVariables, Cci.IImportScope importScopeOpt, ImmutableArray<LambdaDebugInfo> lambdaDebugInfo, ImmutableArray<ClosureDebugInfo> closureDebugInfo, string stateMachineTypeNameOpt, ImmutableArray<Cci.StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes, ImmutableArray<EncHoistedLocalInfo> stateMachineHoistedLocalSlots, ImmutableArray<Cci.ITypeReference> stateMachineAwaiterSlots, Cci.AsyncMethodBodyDebugInfo asyncMethodDebugInfo, DynamicAnalysisMethodBodyData dynamicAnalysisDataOpt) { Debug.Assert(!locals.IsDefault); Debug.Assert(!exceptionHandlers.IsDefault); Debug.Assert(!localScopes.IsDefault); _ilBits = ilBits; _asyncMethodDebugInfo = asyncMethodDebugInfo; _maxStack = maxStack; _parent = parent; _methodId = methodId; _locals = locals; _sequencePoints = sequencePoints; _debugDocumentProvider = debugDocumentProvider; _exceptionHandlers = exceptionHandlers; _localScopes = localScopes; _hasDynamicLocalVariables = hasDynamicLocalVariables; _importScopeOpt = importScopeOpt; _lambdaDebugInfo = lambdaDebugInfo; _closureDebugInfo = closureDebugInfo; _stateMachineTypeNameOpt = stateMachineTypeNameOpt; _stateMachineHoistedLocalScopes = stateMachineHoistedLocalScopes; _stateMachineHoistedLocalSlots = stateMachineHoistedLocalSlots; _stateMachineAwaiterSlots = stateMachineAwaiterSlots; _dynamicAnalysisDataOpt = dynamicAnalysisDataOpt; }
public MethodBody( byte[] ilBits, ushort maxStack, Cci.IMethodDefinition parent, int methodOrdinal, ImmutableArray <Cci.ILocalDefinition> locals, SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider, ImmutableArray <Cci.ExceptionHandlerRegion> exceptionHandlers, ImmutableArray <Cci.LocalScope> localScopes, bool hasDynamicLocalVariables, ImmutableArray <Cci.NamespaceScope> namespaceScopes, Cci.NamespaceScopeEncoding namespaceScopeEncoding, ImmutableArray <LambdaDebugInfo> lambdaDebugInfo, ImmutableArray <ClosureDebugInfo> closureDebugInfo, string stateMachineTypeNameOpt, ImmutableArray <Cci.StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes, ImmutableArray <EncHoistedLocalInfo> stateMachineHoistedLocalSlots, ImmutableArray <Cci.ITypeReference> stateMachineAwaiterSlots, Cci.AsyncMethodBodyDebugInfo asyncMethodDebugInfo) { Debug.Assert(!locals.IsDefault); Debug.Assert(!exceptionHandlers.IsDefault); Debug.Assert(!localScopes.IsDefault); _ilBits = ilBits; _asyncMethodDebugInfo = asyncMethodDebugInfo; _maxStack = maxStack; _parent = parent; _methodOrdinal = methodOrdinal; _locals = locals; _sequencePoints = sequencePoints; _debugDocumentProvider = debugDocumentProvider; _exceptionHandlers = exceptionHandlers; _localScopes = localScopes; _namespaceScopeEncoding = namespaceScopeEncoding; _hasDynamicLocalVariables = hasDynamicLocalVariables; _namespaceScopes = namespaceScopes.IsDefault ? ImmutableArray <Cci.NamespaceScope> .Empty : namespaceScopes; _lambdaDebugInfo = lambdaDebugInfo; _closureDebugInfo = closureDebugInfo; _stateMachineTypeNameOpt = stateMachineTypeNameOpt; _stateMachineHoistedLocalScopes = stateMachineHoistedLocalScopes; _stateMachineHoistedLocalSlots = stateMachineHoistedLocalSlots; _stateMachineAwaiterSlots = stateMachineAwaiterSlots; }
private void RealizeSequencePoints() { if (this.SeqPointsOpt != null) { // we keep track of the latest sequence point location to make sure // we don't emit multiple sequence points for the same location int lastOffset = -1; ArrayBuilder <RawSequencePoint> seqPoints = ArrayBuilder <RawSequencePoint> .GetInstance(); foreach (var seqPoint in this.SeqPointsOpt) { int offset = this.GetILOffsetFromMarker(seqPoint.ILMarker); if (offset >= 0) { // valid IL offset if (lastOffset != offset) { Debug.Assert(lastOffset < offset); // if there are any sequence points, there must // be a sequence point at offset 0. #if !XSHARP Debug.Assert((lastOffset >= 0) || (offset == 0)); #endif // the first sequence point on tree/offset location lastOffset = offset; seqPoints.Add(seqPoint); } else { // override previous sequence point at the same location seqPoints[seqPoints.Count - 1] = seqPoint; } } } if (seqPoints.Count > 0) { this.RealizedSequencePoints = SequencePointList.Create(seqPoints, this); } seqPoints.Free(); } }
private void RealizeSequencePoints() { if (this.SeqPointsOpt != null) { // we keep track of the latest sequence point location to make sure // we don't emit multiple sequence points for the same location int lastOffset = -1; ArrayBuilder<RawSequencePoint> seqPoints = ArrayBuilder<RawSequencePoint>.GetInstance(); foreach (var seqPoint in this.SeqPointsOpt) { int offset = this.GetILOffsetFromMarker(seqPoint.ILMarker); if (offset >= 0) { // valid IL offset if (lastOffset != offset) { Debug.Assert(lastOffset < offset); // if there are any sequence points, there must // be a sequence point at offset 0. Debug.Assert((lastOffset >= 0) || (offset == 0)); // the first sequence point on tree/offset location lastOffset = offset; seqPoints.Add(seqPoint); } else { // override previous sequence point at the same location seqPoints[seqPoints.Count - 1] = seqPoint; } } } if (seqPoints.Count > 0) { this.RealizedSequencePoints = SequencePointList.Create(seqPoints, this); } seqPoints.Free(); } }
/// <summary> /// Get all the sequence points, possibly mapping them using #line/ExternalSource directives, and mapping /// file names to debug documents with the given mapping function. /// </summary> /// <param name="documentProvider">Function that maps file paths to CCI debug documents</param> public ImmutableArray <Cci.SequencePoint> GetSequencePoints(DebugDocumentProvider documentProvider) { bool lastPathIsMapped = false; string lastPath = null; Cci.DebugSourceDocument lastDebugDocument = null; // First, count the number of sequence points. int count = 0; SequencePointList current = this; while (current != null) { count += current._points.Length; current = current._next; } ArrayBuilder <Cci.SequencePoint> result = ArrayBuilder <Cci.SequencePoint> .GetInstance(count); current = this; while (current != null) { SyntaxTree currentTree = current._tree; foreach (var offsetAndSpan in current._points) { TextSpan span = offsetAndSpan.Span; // if it's a hidden sequence point, or a sequence point with syntax that points to a position that is inside // of a hidden region (can be defined with #line hidden (C#) or implicitly by #ExternalSource (VB), make it // a hidden sequence point. bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; FileLinePositionSpan fileLinePositionSpan = default(FileLinePositionSpan); if (!isHidden) { fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden); } if (isHidden) { if (lastPath == null) { lastPath = currentTree.FilePath; lastDebugDocument = documentProvider(lastPath, basePath: null); } if (lastDebugDocument != null) { result.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: HiddenSequencePointLine, startColumn: 0, endLine: HiddenSequencePointLine, endColumn: 0)); } } else { if (lastPath != fileLinePositionSpan.Path || lastPathIsMapped != fileLinePositionSpan.HasMappedPath) { lastPath = fileLinePositionSpan.Path; lastPathIsMapped = fileLinePositionSpan.HasMappedPath; lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? currentTree.FilePath : null); } if (lastDebugDocument != null) { result.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1, startColumn: fileLinePositionSpan.StartLinePosition.Character + 1, endLine: (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1, endColumn: fileLinePositionSpan.EndLinePosition.Character + 1 )); } } } current = current._next; } return(result.ToImmutableAndFree()); }
public void GetSequencePoints( DebugDocumentProvider documentProvider, ArrayBuilder <Cci.SequencePoint> builder ) { bool lastPathIsMapped = false; string lastPath = null; Cci.DebugSourceDocument lastDebugDocument = null; FileLinePositionSpan?firstReal = FindFirstRealSequencePoint(); if (!firstReal.HasValue) { return; } lastPath = firstReal.Value.Path; lastPathIsMapped = firstReal.Value.HasMappedPath; lastDebugDocument = documentProvider( lastPath, basePath: lastPathIsMapped ? this._tree.FilePath : null ); SequencePointList current = this; while (current != null) { SyntaxTree currentTree = current._tree; foreach (var offsetAndSpan in current._points) { TextSpan span = offsetAndSpan.Span; // if it's a hidden sequence point, or a sequence point with syntax that points to a position that is inside // of a hidden region (can be defined with #line hidden (C#) or implicitly by #ExternalSource (VB), make it // a hidden sequence point. bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; FileLinePositionSpan fileLinePositionSpan = default; if (!isHidden) { fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility( span, out isHidden ); } if (isHidden) { if (lastPath == null) { lastPath = currentTree.FilePath; lastDebugDocument = documentProvider(lastPath, basePath: null); } if (lastDebugDocument != null) { builder.Add( new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: Cci.SequencePoint.HiddenLine, startColumn: 0, endLine: Cci.SequencePoint.HiddenLine, endColumn: 0 ) ); } } else { if ( lastPath != fileLinePositionSpan.Path || lastPathIsMapped != fileLinePositionSpan.HasMappedPath ) { lastPath = fileLinePositionSpan.Path; lastPathIsMapped = fileLinePositionSpan.HasMappedPath; lastDebugDocument = documentProvider( lastPath, basePath: lastPathIsMapped ? currentTree.FilePath : null ); } if (lastDebugDocument != null) { int startLine = (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1; int endLine = (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1; int startColumn = fileLinePositionSpan.StartLinePosition.Character + 1; int endColumn = fileLinePositionSpan.EndLinePosition.Character + 1; // Trim column number if necessary. // Column must be in range [0, 0xffff) and end column must be greater than start column if on the same line. // The Portable PDB specifies 0x10000, but System.Reflection.Metadata reader has an off-by-one error. // Windows PDBs allow the same range. const int MaxColumn = ushort.MaxValue - 1; if (startColumn > MaxColumn) { startColumn = (startLine == endLine) ? MaxColumn - 1 : MaxColumn; } if (endColumn > MaxColumn) { endColumn = MaxColumn; } builder.Add( new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: startLine, startColumn: (ushort)startColumn, endLine: endLine, endColumn: (ushort)endColumn ) ); } } } current = current._next; } }
/// <summary> /// Get all the sequence points, possibly mapping them using #line/ExternalSource directives, and mapping /// file names to debug documents with the given mapping function. /// </summary> /// <param name="documentProvider">Function that maps file paths to CCI debug documents</param> /// <param name="builder">where sequence points should be deposited</param> public void GetSequencePoints( DebugDocumentProvider documentProvider, ArrayBuilder <Cci.SequencePoint> builder) { bool lastPathIsMapped = false; string lastPath = null; Cci.DebugSourceDocument lastDebugDocument = null; FileLinePositionSpan?firstReal = FindFirstRealSequencePoint(); if (!firstReal.HasValue) { return; } lastPath = firstReal.Value.Path; lastPathIsMapped = firstReal.Value.HasMappedPath; lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? this._tree.FilePath : null); SequencePointList current = this; while (current != null) { SyntaxTree currentTree = current._tree; foreach (OffsetAndSpan offsetAndSpan in current._points) { TextSpan span = offsetAndSpan.Span; // if it's a hidden sequence point, or a sequence point with syntax that points to a position that is inside // of a hidden region (can be defined with #line hidden (C#) or implicitly by #ExternalSource (VB), make it // a hidden sequence point. bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; FileLinePositionSpan fileLinePositionSpan = default(FileLinePositionSpan); if (!isHidden) { fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden); } if (isHidden) { if (lastPath == null) { lastPath = currentTree.FilePath; lastDebugDocument = documentProvider(lastPath, basePath: null); } if (lastDebugDocument != null) { builder.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: HiddenSequencePointLine, startColumn: 0, endLine: HiddenSequencePointLine, endColumn: 0)); } } else { if (lastPath != fileLinePositionSpan.Path || lastPathIsMapped != fileLinePositionSpan.HasMappedPath) { lastPath = fileLinePositionSpan.Path; lastPathIsMapped = fileLinePositionSpan.HasMappedPath; lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? currentTree.FilePath : null); } if (lastDebugDocument != null) { builder.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1, startColumn: fileLinePositionSpan.StartLinePosition.Character + 1, endLine: (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1, endColumn: fileLinePositionSpan.EndLinePosition.Character + 1 )); } } } current = current._next; } }