protected internal override bool Walk(TryStatement node) { ExceptionBlock block = new ExceptionBlock(node); _tryBlocks.Push(block); WalkNode(node.Body); IList<CatchBlock> handlers = node.Handlers; if (handlers != null) { block.State = ExceptionBlock.TryStatementState.Handler; for (int handler = 0; handler < handlers.Count; handler++) { block.Handler = handler; WalkNode(handlers[handler].Body); } } if (node.FinallyStatement != null) { block.State = ExceptionBlock.TryStatementState.Finally; WalkNode(node.FinallyStatement); } Debug.Assert((object)block == (object)_tryBlocks.Peek()); _tryBlocks.Pop(); return false; }
public Label BeginExceptionBlock() { ExceptionBlock block = new ExceptionBlock(exceptions.Count); block.labelEnd = DefineLabel(); block.tryOffset = code.Position; exceptionStack.Push(block); exceptions.Add(block); stackHeight = 0; return block.labelEnd; }
ExceptionBlock GetTryBlock() { ExceptionBlock tryBlk = GetBlock() as ExceptionBlock; if (tryBlk == null) { throw new InvalidOperationException("Statement can be used only in an exception block"); } return(tryBlk); }
ExceptionBlock GetTryBlock() { ExceptionBlock tryBlk = GetBlock() as ExceptionBlock; if (tryBlk == null) { throw new InvalidOperationException(Messages.ErrInvalidExceptionStatement); } return(tryBlk); }
public void BeginCatchBlock(Type exceptionType) { ExceptionBlock block = exceptionStack.Peek(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { if (exceptionType == null) { Emit(OpCodes.Endfilter); } else { Emit(OpCodes.Leave, block.labelEnd); } } stackHeight = 0; UpdateStack(1); if (exceptionType == null) { if (block.exceptionType != MarkerType.Filter || block.handlerOffset != 0) { throw new ArgumentNullException("exceptionType"); } block.handlerOffset = code.Position; } else { if (block.tryLength == 0) { block.tryLength = code.Position - block.tryOffset; } else { block.handlerLength = code.Position - block.handlerOffset; exceptionStack.Pop(); ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); newBlock.labelEnd = block.labelEnd; newBlock.tryOffset = block.tryOffset; newBlock.tryLength = block.tryLength; block = newBlock; exceptions.Add(block); exceptionStack.Push(block); } block.exceptionType = exceptionType; if (exceptionType == MarkerType.Filter) { block.filterOffset = code.Position; } else { block.handlerOffset = code.Position; } } }
public override bool Walk(TryFinallyStmt node) { TryFinallyBlock tfb = new TryFinallyBlock(node); tryBlocks.Push(tfb); node.body.Walk(this); tfb.state = ExceptionBlock.State.Finally; node.finallyStmt.Walk(this); ExceptionBlock eb = tryBlocks.Pop(); Debug.Assert((object)eb == (object)tfb); return(false); }
ExceptionBlock GetAnyTryBlock() { foreach (Block blk in blocks) { ExceptionBlock tryBlk = blk as ExceptionBlock; if (tryBlk != null) { return(tryBlk); } } return(null); }
public void EndExceptionBlock() { ExceptionBlock block = exceptionStack.Pop(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { if (block.filterOffset != 0 || (block.exceptionType != MarkerType.Finally && block.exceptionType != MarkerType.Fault)) { Emit(OpCodes.Leave, block.labelEnd); } else { Emit(OpCodes.Endfinally); } } MarkLabel(block.labelEnd); block.handlerLength = code.Position - block.handlerOffset; }
public override void PostWalk(YieldStmt node) { topYields[node.index] = new YieldTarget(cg.DefineLabel()); if (tryBlocks.Count == 0) { node.label = topYields[node.index].topBranchTarget; } else if (tryBlocks.Count == 1) { ExceptionBlock eb = tryBlocks.Peek(); eb.AddYieldTarget(node, topYields[node.index], cg); } else { throw new NotImplementedException("yield in more than one try block"); } }
public void EndExceptionBlock() { ExceptionBlock block = exceptionStack.Pop(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { if (block.kind != ExceptionHandlingClauseOptions.Finally && block.kind != ExceptionHandlingClauseOptions.Fault) { Emit(OpCodes.Leave, block.labelEnd); } else { Emit(OpCodes.Endfinally); } } MarkLabel(block.labelEnd); block.handlerLength = code.Position - block.handlerOffset; }
public void EndHandler(ExceptionBlock block, LabelledExceptionHandler handler) { switch (handler.handlerType) { case ExceptionHandlerType.Filter: Emit(OpCodes.Endfilter); break; case ExceptionHandlerType.Finally: Emit(OpCodes.Endfinally); break; default: Emit(OpCodes.Leave, block.skip); break; } MarkLabel(block.skip); pendingExceptionHandlers.Add(block.cur); }
public void EndExceptionBlock() { ExceptionBlock block = exceptionStack.Pop(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { if (block.filterOffset != 0 || (block.exceptionType != null && block.exceptionType != FAULT)) { Emit(OpCodes.Leave, block.labelEnd); } else { Emit(OpCodes.Endfinally); } if (IsLabelReachable(block.labelEnd)) { MarkLabel(block.labelEnd); } } block.handlerLength = code.Position - block.handlerOffset; }
private void BeginFinallyFaultBlock(Type type) { ExceptionBlock block = exceptionStack.Peek(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { Emit(OpCodes.Leave, block.labelEnd); } if (block.handlerOffset == 0) { block.tryLength = code.Position - block.tryOffset; } else { block.handlerLength = code.Position - block.handlerOffset; Label labelEnd; if (exceptionBlockAssistanceMode != EBAM_COMPAT) { labelEnd = block.labelEnd; } else { MarkLabel(block.labelEnd); labelEnd = DefineLabel(); Emit(OpCodes.Leave, labelEnd); } exceptionStack.Pop(); ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); newBlock.labelEnd = labelEnd; newBlock.tryOffset = block.tryOffset; newBlock.tryLength = code.Position - block.tryOffset; block = newBlock; exceptions.Add(block); exceptionStack.Push(block); } block.handlerOffset = code.Position; block.exceptionType = type; stackHeight = 0; }
private ExceptionBlock BeginFinallyFilterFaultBlock() { ExceptionBlock block = exceptionStack.Peek(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { Emit(OpCodes.Leave, block.labelEnd); } stackHeight = 0; if (block.handlerOffset == 0) { block.tryLength = code.Position - block.tryOffset; } else { block.handlerLength = code.Position - block.handlerOffset; bool reachable = IsLabelReachable(block.labelEnd); Label labelEnd = new Label(); if (reachable) { MarkLabel(block.labelEnd); } labelEnd = DefineLabel(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && reachable)) { Emit(OpCodes.Leave, labelEnd); } exceptionStack.Pop(); ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); newBlock.labelEnd = labelEnd; newBlock.tryOffset = block.tryOffset; newBlock.tryLength = code.Position - block.tryOffset; block = newBlock; exceptions.Add(block); exceptionStack.Push(block); } return(block); }
public override bool Walk(TryStmt node) { TryBlock tb = new TryBlock(node); tryBlocks.Push(tb); node.body.Walk(this); tb.state = TryBlock.State.Handler; foreach (TryStmtHandler handler in node.handlers) { handler.Walk(this); } ExceptionBlock eb = tryBlocks.Pop(); Debug.Assert((object)tb == (object)eb); if (node.elseStmt != null) { node.elseStmt.Walk(this); } return(false); }
public void BeginFinallyBlock() { ExceptionBlock block = BeginFinallyFilterFaultBlock(); block.handlerOffset = code.Position; }
/// <summary> /// Write method body to a ILDasm -like representation /// </summary> /// <param name="mb">Method body to write</param> /// <returns>String representation of the method body (locals and instruction)</returns> /// <exception cref="ArgumentOutOfRangeException">Unexpected exception block type</exception> public static string ToILDasmString(this MethodBody mb) { var sb = new StringBuilder(); var instrs = mb.Instructions; // Fixup the the offsets var prev = instrs.First(); prev.Offset = 0; foreach (var ins in instrs.Skip(1)) { var operand = prev.Operand; if (operand is ILLabel label) { prev.Operand = label.Target; } else if (operand is ILLabel[] labels) { prev.Operand = labels.Select(l => l.Target).ToArray(); } ins.Offset = prev.Offset + prev.GetSize(); prev.Operand = operand; prev = ins; } // Cache exception blocks for pretty printing var exBlocks = new Dictionary <Instruction, List <ExceptionBlock> >(); ExceptionBlock AddBlock(Instruction ins, ExceptionBlockType t) { if (ins == null) { return(new ExceptionBlock(0)); } if (!exBlocks.TryGetValue(ins, out var list)) { exBlocks[ins] = list = new List <ExceptionBlock>(); } var block = new ExceptionBlock(t); list.Add(block); return(block); } foreach (var exHandler in mb.ExceptionHandlers) { AddBlock(exHandler.TryStart, ExceptionBlockType.BeginExceptionBlock); AddBlock(exHandler.TryEnd, ExceptionBlockType.EndExceptionBlock); AddBlock(exHandler.HandlerEnd, ExceptionBlockType.EndExceptionBlock); switch (exHandler.HandlerType) { case ExceptionHandlerType.Catch: AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginCatchBlock).catchType = exHandler.CatchType.ResolveReflection(); break; case ExceptionHandlerType.Filter: AddBlock(exHandler.FilterStart, ExceptionBlockType.BeginExceptFilterBlock); break; case ExceptionHandlerType.Finally: AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginFinallyBlock); break; case ExceptionHandlerType.Fault: AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginFaultBlock); break; default: throw new ArgumentOutOfRangeException(); } } var indent = 0; const int indentAmount = 2; void WriteLine(string text) { sb.Append(new string(' ', indent)).AppendLine(text); } WriteLine(".locals init ("); indent += indentAmount * 2; for (var index = 0; index < mb.Variables.Count; index++) { var variableDefinition = mb.Variables[index]; WriteLine($"{variableDefinition.VariableType.FullName} V_{index}"); } indent -= indentAmount * 2; WriteLine(")"); var handlerStack = new Stack <string>(); foreach (var ins in instrs) { var blocks = exBlocks.GetValueSafe(ins) ?? new List <ExceptionBlock>(); // Force exception close to the start for correct output blocks.Sort((a, b) => a.blockType == ExceptionBlockType.EndExceptionBlock ? -1 : 0); foreach (var exceptionBlock in blocks) { switch (exceptionBlock.blockType) { case ExceptionBlockType.BeginExceptionBlock: WriteLine(".try"); WriteLine("{"); indent += indentAmount; handlerStack.Push(".try"); break; case ExceptionBlockType.BeginCatchBlock: WriteLine($"catch {exceptionBlock.catchType.FullName}"); WriteLine("{"); indent += indentAmount; handlerStack.Push("handler (catch)"); break; case ExceptionBlockType.BeginExceptFilterBlock: WriteLine("filter"); WriteLine("{"); indent += indentAmount; handlerStack.Push("handler (filter)"); break; case ExceptionBlockType.BeginFaultBlock: WriteLine("fault"); WriteLine("{"); indent += indentAmount; handlerStack.Push("handler (fault)"); break; case ExceptionBlockType.BeginFinallyBlock: WriteLine("finally"); WriteLine("{"); indent += indentAmount; handlerStack.Push("handler (finally)"); break; case ExceptionBlockType.EndExceptionBlock: indent -= indentAmount; WriteLine($"}} // end {handlerStack.Pop()}"); break; default: throw new ArgumentOutOfRangeException(); } } var operand = ins.Operand; if (operand is ILLabel label) { ins.Operand = label.Target; } else if (operand is ILLabel[] labels) { ins.Operand = labels.Select(l => l.Target).ToArray(); } WriteLine(ins.ToString()); ins.Operand = operand; } return(sb.ToString()); }
public void AddEvent(ILConversion conversion, ExceptionBlockEventKind eventKind, ExceptionHandlingInfo handlingInfo, int offset, ExceptionBlock exceptionBlock) { AddEvent(conversion, eventKind, handlingInfo, offset, exceptionBlock, null); }
public void AddEvent(ILConversion conversion, ExceptionBlockEventKind eventKind, ExceptionHandlingInfo handlingInfo, int offset, ExceptionBlock exceptionBlock, ExceptionHandler exceptionHandler) { var entry = new ExceptionBlockEventEntry() { ExceptionBlock = exceptionBlock, Kind = eventKind, Offset = offset, ExceptionHandler = exceptionHandler }; if (!handlingInfo.Events.TryGetValue(offset, out List <ExceptionBlockEventEntry> eventList)) { eventList = new List <ExceptionBlockEventEntry>(); handlingInfo.Events.Add(offset, eventList); } eventList.Add(entry); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" /> public EmitShorthand BeginFinallyBlock(ExceptionBlock forTry, out FinallyBlock forFinally) { forFinally = BeginFinallyBlock(forTry); return(this); }
private static string ExceptionBlockToString(ExceptionBlock block) { return($"{block.blockType}|{block.catchType.AssemblyQualifiedName}"); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" /> public CatchBlock BeginCatchBlock <ExceptionType>(ExceptionBlock forTry) { return(BeginCatchBlock(forTry, typeof(ExceptionType))); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" /> public EmitShorthand BeginCatchBlock <ExceptionType>(ExceptionBlock forTry, out CatchBlock tryCatch) { tryCatch = BeginCatchBlock <ExceptionType>(forTry); return(this); }
public void EndExceptionBlock(ExceptionBlock block) { EndHandler(block, block.cur); }
/// <summary> /// Deep-copies the exception block. /// </summary> /// <param name="block">The exception block to clone.</param> /// <returns>The cloned exception block.</returns> public static ExceptionBlock Clone(this ExceptionBlock block) { return(new ExceptionBlock(block.blockType, block.catchType)); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginExceptionBlock" /> public EmitShorthand BeginExceptionBlock(out ExceptionBlock forTry) { forTry = BeginExceptionBlock(); return(this); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.EndExceptionBlock(Sigil.ExceptionBlock)" /> public EmitShorthand EndExceptionBlock(ExceptionBlock forTry) { InnerEmit.EndExceptionBlock(forTry); return(this); }
public virtual T Visit(ExceptionBlock node) { Visit((Statement)node); traverse(node.onList); return(traverse(node.@default)); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" /> public EmitShorthand BeginCatchBlock(ExceptionBlock forTry, Type exceptionType, out CatchBlock forCatch) { forCatch = BeginCatchBlock(forTry, exceptionType); return(this); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" /> public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType) { return(InnerEmit.BeginCatchBlock(forTry, exceptionType)); }
/// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" /> public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry) { return(InnerEmit.BeginFinallyBlock(forTry)); }