public CompiledTryCatchFinallyBlock(TryCatchFinallyBlock block) { BeginTry = block.BeginTry; BeginCatch = block.BeginCatch; BeginFinally = block.BeginFinally; EndTry = block.EndTry; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Value) throw new NotSupportedException("Try-catch-finally blocks cannot be used with value stack semantics (They don't produce values)"); var prefix = "try\\" + Guid.NewGuid().ToString("N") + "\\"; var beginTryLabel = prefix + "beginTry"; var beginFinallyLabel = prefix + "beginFinally"; var beginCatchLabel = prefix + "beginCatch"; var endTry = prefix + "endTry"; if (TryBlock.IsEmpty) if (FinallyBlock.IsEmpty) return; else { //The finally block is not protected // A trycatchfinally with just a finally block is equivalent to the contents of the finally block // " try {} finally { $code } " => " $code " FinallyBlock.EmitEffectCode(target); return; } //Emit try block target.EmitLabel(Position, beginTryLabel); target.Emit(Position,OpCode.@try); TryBlock.EmitEffectCode(target); //Emit finally block target.EmitLabel(FinallyBlock.Position, beginFinallyLabel); var beforeEmit = target.Code.Count; FinallyBlock.EmitEffectCode(target); if (FinallyBlock.Count > 0 && target.Code.Count == beforeEmit) target.Emit(FinallyBlock.Position, OpCode.nop); target.EmitLeave(FinallyBlock.Position, endTry); //Emit catch block target.EmitLabel(CatchBlock.Position, beginCatchLabel); var usesException = ExceptionVar != null; var justRethrow = CatchBlock.IsEmpty && !usesException; if (usesException) { //Assign exception ExceptionVar = _GetOptimizedNode(target, ExceptionVar) as AstGetSet ?? ExceptionVar; ExceptionVar.Arguments.Add(new AstGetException(File, Line, Column)); ExceptionVar.Call = PCall.Set; ExceptionVar.EmitEffectCode(target); } if (!justRethrow) { //Exception handled CatchBlock.EmitEffectCode(target); } else { //Exception not handled => rethrow. // * Rethrow is implemented in the runtime * //AstThrow th = new AstThrow(File, Line, Column); //th.Expression = new AstGetException(File, Line, Column); //th.EmitCode(target); } target.EmitLabel(Position, endTry); target.Emit(Position,OpCode.nop); var block = new TryCatchFinallyBlock( _getAddress(target, beginTryLabel), _getAddress(target, endTry)) { BeginFinally = (!FinallyBlock.IsEmpty ? _getAddress(target, beginFinallyLabel) : -1), BeginCatch = (!justRethrow ? _getAddress(target, beginCatchLabel) : -1), UsesException = usesException }; //Register try-catch-finally block target.Function.Meta.AddTo(TryCatchFinallyBlock.MetaKey, block); target.Function.InvalidateTryCatchFinallyBlocks(); }
public TryCatchFinallyBlock Build() { var tryCatchFinallyBlock = new TryCatchFinallyBlock(_block); tryCatchFinallyBlock.TryBlock = new TryBlockBuilder(_reader, _block).Build(); /* * build catch block or finally block * */ if (!_reader.HasNext()) { return(tryCatchFinallyBlock); } _reader.Next(); if (_reader.Current().Value == Keywords.FINALLY) { tryCatchFinallyBlock.FinallyBlock = new FinalyBlockBuilder(_reader, _block).Build(); return(tryCatchFinallyBlock); } else if (_reader.Current().Value == Keywords.CATCH) { tryCatchFinallyBlock.CatchBlock = new CatchBuilder(_reader, _block).Build(); } else { _reader.Back(); return(tryCatchFinallyBlock); } /* * build finally block * */ if (!_reader.HasNext()) { return(tryCatchFinallyBlock); } _reader.Next(); if (_reader.Current().Value == Keywords.FINALLY) { /* * finally block has been set; */ if (tryCatchFinallyBlock.FinallyBlock != null) { throwError("incorrect try-catch-finally block!"); } tryCatchFinallyBlock.FinallyBlock = new FinalyBlockBuilder(_reader, _block).Build(); } else if (_reader.Current().Value == Keywords.CATCH) { /* * can not exist mutiple catch block or finally block before catch block */ throwError("incorrect try-catch-finally block!"); } else { _reader.Back(); return(tryCatchFinallyBlock); } return(tryCatchFinallyBlock); }
public static CompiledTryCatchFinallyBlock Create(TryCatchFinallyBlock block) { return new CompiledTryCatchFinallyBlock(block); }
public override bool TryHandleException(Exception exc) { //Pointer has already been incremented. var address = _pointer - 1; var block = TryCatchFinallyBlock.Closest(address, _implementation.TryCatchFinallyBlocks); if (block == null) //No try-catch-finally block handles exceptions at the given address. return false; _currentException = exc; if (block.HasFinally) { #if Verbose Console.WriteLine("Exception handled by finally-catch. " + block); #endif _isHandlingException.Pop(); _isHandlingException.Push(true); _pointer = block.BeginFinally; _currentTry = block; } else if (block.HasCatch) { #if Verbose Console.WriteLine("Exception handled by catch." + block); #endif _pointer = block.BeginCatch; } else { //Fix #9 (Different handling of exception blocks in CIL implementation) // The CLR defaults to rethrowing exceptions. return false; } return true; }