diff --git a/src/tools/crossgen2/Common/TypeSystem/IL/MethodILDebugView.cs b/src/tools/crossgen2/Common/TypeSystem/IL/MethodILDebugView.cs index 1f5fbcb4a0d5..e0d5675e6022 100644 --- a/src/tools/crossgen2/Common/TypeSystem/IL/MethodILDebugView.cs +++ b/src/tools/crossgen2/Common/TypeSystem/IL/MethodILDebugView.cs @@ -92,10 +92,45 @@ public string Disassembly } sb.AppendLine(); - // TODO: exception regions + const string pad = " "; + + // TODO: pretty exception regions + foreach (ILExceptionRegion region in _methodIL.GetExceptionRegions()) + { + sb.Append(pad); + sb.Append(".try "); + ILDisassembler.AppendOffset(sb, region.TryOffset); + sb.Append(" to "); + ILDisassembler.AppendOffset(sb, region.TryOffset + region.TryLength); + + switch (region.Kind) + { + case ILExceptionRegionKind.Catch: + sb.Append(" catch "); + disasm.AppendType(sb, (TypeDesc)_methodIL.GetObject(region.ClassToken)); + break; + case ILExceptionRegionKind.Fault: + sb.Append(" fault"); + break; + case ILExceptionRegionKind.Filter: + sb.Append(" filter "); + ILDisassembler.AppendOffset(sb, region.FilterOffset); + break; + case ILExceptionRegionKind.Finally: + sb.Append(" finally"); + break; + } + + sb.Append(" handler "); + ILDisassembler.AppendOffset(sb, region.HandlerOffset); + sb.Append(" to "); + ILDisassembler.AppendOffset(sb, region.HandlerOffset + region.HandlerLength); + sb.AppendLine(); + } + while (disasm.HasNextInstruction) { - sb.Append(" "); + sb.Append(pad); sb.AppendLine(disasm.GetNextInstruction()); } diff --git a/src/tools/crossgen2/Common/TypeSystem/IL/Stubs/ILEmitter.cs b/src/tools/crossgen2/Common/TypeSystem/IL/Stubs/ILEmitter.cs index 45627bd1d751..ec272c85461b 100644 --- a/src/tools/crossgen2/Common/TypeSystem/IL/Stubs/ILEmitter.cs +++ b/src/tools/crossgen2/Common/TypeSystem/IL/Stubs/ILEmitter.cs @@ -14,6 +14,8 @@ namespace Internal.IL.Stubs { public class ILCodeStream { + private const int StartOffsetNotSet = -1; + private struct LabelAndOffset { public readonly ILCodeLabel Label; @@ -37,10 +39,16 @@ public LabelAndOffset(ILCodeLabel label, int offset) internal ILCodeStream(ILEmitter emitter) { _instructions = Array.Empty(); - _startOffsetForLinking = -1; + _startOffsetForLinking = StartOffsetNotSet; _emitter = emitter; } + internal int RelativeToAbsoluteOffset(int relativeOffset) + { + Debug.Assert(_startOffsetForLinking != StartOffsetNotSet); + return _startOffsetForLinking + relativeOffset; + } + private void EmitByte(byte b) { if (_instructions.Length == _length) @@ -417,6 +425,34 @@ public void EmitLabel(ILCodeLabel label) label.Place(this, _length); } + public void BeginTry(ILExceptionRegionBuilder builder) + { + Debug.Assert(builder._beginTryStream == null); + builder._beginTryStream = this; + builder._beginTryOffset = _length; + } + + public void EndTry(ILExceptionRegionBuilder builder) + { + Debug.Assert(builder._endTryStream == null); + builder._endTryStream = this; + builder._endTryOffset = _length; + } + + public void BeginHandler(ILExceptionRegionBuilder builder) + { + Debug.Assert(builder._beginHandlerStream == null); + builder._beginHandlerStream = this; + builder._beginHandlerOffset = _length; + } + + public void EndHandler(ILExceptionRegionBuilder builder) + { + Debug.Assert(builder._endHandlerStream == null); + builder._endHandlerStream = this; + builder._endHandlerOffset = _length; + } + internal void PatchLabels() { for (int i = 0; i < _offsetsNeedingPatching.Count; i++) @@ -424,7 +460,7 @@ internal void PatchLabels() LabelAndOffset patch = _offsetsNeedingPatching[i]; Debug.Assert(patch.Label.IsPlaced); - Debug.Assert(_startOffsetForLinking > -1); + Debug.Assert(_startOffsetForLinking != StartOffsetNotSet); int offset = patch.Offset; @@ -456,6 +492,34 @@ public void DefineSequencePoint(string document, int lineNumber) } } + public class ILExceptionRegionBuilder + { + internal ILCodeStream _beginTryStream; + internal int _beginTryOffset; + + internal ILCodeStream _endTryStream; + internal int _endTryOffset; + + internal ILCodeStream _beginHandlerStream; + internal int _beginHandlerOffset; + + internal ILCodeStream _endHandlerStream; + internal int _endHandlerOffset; + + internal ILExceptionRegionBuilder() + { + } + + internal int TryOffset => _beginTryStream.RelativeToAbsoluteOffset(_beginTryOffset); + internal int TryLength => _endTryStream.RelativeToAbsoluteOffset(_endTryOffset) - TryOffset; + internal int HandlerOffset => _beginHandlerStream.RelativeToAbsoluteOffset(_beginHandlerOffset); + internal int HandlerLength => _endHandlerStream.RelativeToAbsoluteOffset(_endHandlerOffset) - HandlerOffset; + + internal bool IsDefined => + _beginTryStream != null && _endTryStream != null + && _beginHandlerStream != null && _endHandlerStream != null; + } + /// /// Represent a token. Use one of the overloads of /// to create a new token. @@ -473,12 +537,13 @@ public class ILStubMethodIL : MethodIL private readonly LocalVariableDefinition[] _locals; private readonly Object[] _tokens; private readonly MethodDesc _method; + private readonly ILExceptionRegion[] _exceptionRegions; private readonly MethodDebugInformation _debugInformation; private const int MaxStackNotSet = -1; private int _maxStack; - public ILStubMethodIL(MethodDesc owningMethod, byte[] ilBytes, LocalVariableDefinition[] locals, Object[] tokens, MethodDebugInformation debugInfo = null) + public ILStubMethodIL(MethodDesc owningMethod, byte[] ilBytes, LocalVariableDefinition[] locals, Object[] tokens, ILExceptionRegion[] exceptionRegions = null, MethodDebugInformation debugInfo = null) { _ilBytes = ilBytes; _locals = locals; @@ -486,6 +551,10 @@ public ILStubMethodIL(MethodDesc owningMethod, byte[] ilBytes, LocalVariableDefi _method = owningMethod; _maxStack = MaxStackNotSet; + if (exceptionRegions == null) + exceptionRegions = Array.Empty(); + _exceptionRegions = exceptionRegions; + if (debugInfo == null) debugInfo = MethodDebugInformation.None; _debugInformation = debugInfo; @@ -531,7 +600,7 @@ public override int MaxStack public override ILExceptionRegion[] GetExceptionRegions() { - return Array.Empty(); + return _exceptionRegions; } public override bool IsInitLocals { @@ -569,8 +638,7 @@ internal int AbsoluteOffset get { Debug.Assert(IsPlaced); - Debug.Assert(_codeStream._startOffsetForLinking >= 0); - return _codeStream._startOffsetForLinking + _offsetWithinCodeStream; + return _codeStream.RelativeToAbsoluteOffset(_offsetWithinCodeStream); } } @@ -591,6 +659,7 @@ public class ILEmitter private ArrayBuilder _codeStreams; private ArrayBuilder _locals; private ArrayBuilder _tokens; + private ArrayBuilder _finallyRegions; public ILEmitter() { @@ -648,6 +717,13 @@ public ILCodeLabel NewCodeLabel() return newLabel; } + public ILExceptionRegionBuilder NewFinallyRegion() + { + var region = new ILExceptionRegionBuilder(); + _finallyRegions.Add(region); + return region; + } + public MethodIL Link(MethodDesc owningMethod) { int totalLength = 0; @@ -694,7 +770,26 @@ public MethodIL Link(MethodDesc owningMethod) debugInfo = new EmittedMethodDebugInformation(sequencePoints); } - var result = new ILStubMethodIL(owningMethod, ilInstructions, _locals.ToArray(), _tokens.ToArray(), debugInfo); + ILExceptionRegion[] exceptionRegions = null; + + int numberOfExceptionRegions = _finallyRegions.Count; + if (numberOfExceptionRegions > 0) + { + exceptionRegions = new ILExceptionRegion[numberOfExceptionRegions]; + + for (int i = 0; i < _finallyRegions.Count; i++) + { + ILExceptionRegionBuilder region = _finallyRegions[i]; + + Debug.Assert(region.IsDefined); + + exceptionRegions[i] = new ILExceptionRegion(ILExceptionRegionKind.Finally, + region.TryOffset, region.TryLength, region.HandlerOffset, region.HandlerLength, + classToken: 0, filterOffset: 0); + } + } + + var result = new ILStubMethodIL(owningMethod, ilInstructions, _locals.ToArray(), _tokens.ToArray(), exceptionRegions, debugInfo); result.CheckStackBalance(); return result; }