internal void GenCall(CodeGenContext context) { int result = context.CreateLocal("result", PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); PERWAPI.CILLabel retryLabel = context.NewLabel(); context.CodeLabel(retryLabel); context.StartBlock(Clause.Try); { // object result = Call(...) GenCall0(context); context.stloc(result); context.Goto(endLabel); } PERWAPI.TryBlock tryBlock = context.EndTryBlock(); context.StartBlock(Clause.Catch); { CatchBreakException(context, result, endLabel); } context.EndCatchBlock(Runtime.BreakExceptionRef, tryBlock); context.StartBlock(Clause.Catch); { CatchRetryException(context, retryLabel); } context.EndCatchBlock(Runtime.RetryExceptionRef, tryBlock); context.CodeLabel(endLabel); context.ldloc(result); context.ReleaseLocal(result, true); }
internal override void GenCode0(CodeGenContext context) { PERWAPI.CILLabel finalLabel = context.NewLabel(); int RescueTemp = context.CreateLocal("rescueTemp", PERWAPI.PrimitiveType.Object); context.ldnull(); context.stloc(RescueTemp); if (ensure != null) { context.StartBlock(Clause.Try); // outer try block with finally context.StartBlock(Clause.Try); // inner try block with catch } GenInnerBlock(context, RescueTemp); if (ensure != null) { context.Goto(finalLabel); PERWAPI.TryBlock innerTry = context.EndTryBlock(); context.StartBlock(Clause.Catch); GenRescue(context, null, 0, null); context.EndCatchBlock(Runtime.SystemExceptionRef, innerTry); PERWAPI.TryBlock outerTry = context.EndTryBlock(); // Fixme: reset labels to prevent branches out of finally block. context.StartBlock(Clause.Finally); ensure.GenCode(context); if (context.Reachable()) context.pop(); context.endfinally(); context.EndFinallyBlock(outerTry); context.CodeLabel(finalLabel); context.newEndPoint(location); } context.ldloc(RescueTemp); context.ReleaseLocal(RescueTemp, true); }
internal void CatchReturnException(CodeGenContext context, PERWAPI.TryBlock tryBlock) { // catch (Ruby.ReturnException exception) { ... } context.StartBlock(Clause.Catch); { PERWAPI.CILLabel falseLabel = context.NewLabel(); int exception = context.StoreInTemp("exception", Runtime.ReturnExceptionRef, location); // if (exception.scope == thisframe) context.ldloc(exception); context.ldfld(Runtime.ReturnException.scope); context.ldloc(0); context.bne(falseLabel); // returnTemp = exception.return_value; context.ldloc(exception); context.ldfld(Runtime.ReturnException.return_value); context.stloc(returnTemp); context.Goto(context.labels.Return); // falseLabel: context.CodeLabel(falseLabel); // throw exception context.rethrow(); context.ReleaseLocal(exception, true); } context.EndCatchBlock(Runtime.ReturnExceptionRef, tryBlock); }
internal override void Defined(CodeGenContext context) { if (qualified) if (scope != null) { // object result; int result = context.CreateLocal("result", PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); // try { context.StartBlock(Clause.Try); { // result = Eval.const_defined(scope, vid, caller); scope.GenCode(context); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); context.stloc(result); context.leave(endLabel); } TryBlock block = context.EndTryBlock(); // catch (System.Exception) { context.StartBlock(Clause.Catch); { // result = null; context.ldnull(); context.stloc(result); context.leave(endLabel); } context.EndCatchBlock(Runtime.SystemExceptionRef, block); context.CodeLabel(endLabel); context.ldloc(result); context.ReleaseLocal(result, true); } else { context.ldsfld(Ruby.Compiler.Runtime.Init.rb_cObject); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); } else { context.ruby_cbase(parent_scope); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); } }
private void GenInnerBlock(CodeGenContext context, int RescueTemp) { PERWAPI.CILLabel elseLabel = context.NewLabel(); Labels catchLabels = new Labels(); catchLabels.Break = context.labels.Break; catchLabels.Next = context.labels.Next; catchLabels.Redo = context.labels.Redo; catchLabels.Return = context.labels.Return; catchLabels.Retry = context.NewLabel(); context.CodeLabel(catchLabels.Retry); context.StartBlock(Clause.Try); { if (body != null) body.GenCode(context); else context.ldnull(); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(elseLabel); } } PERWAPI.TryBlock innerTry = context.EndTryBlock(); PERWAPI.CILLabel endLabel = context.NewLabel(); if (rescue != null) { context.StartBlock(Clause.Catch); { Labels original = context.labels; context.labels = catchLabels; GenRescue(context, endLabel, RescueTemp, rescue); context.labels = original; } context.EndCatchBlock(Runtime.SystemExceptionRef, innerTry); } context.CodeLabel(elseLabel); { if (_else != null) { _else.GenCode(context); if (context.Reachable()) context.stloc(RescueTemp); } } context.CodeLabel(endLabel); }
internal override void GenCode0(CodeGenContext context) { int RescueTemp = context.CreateLocal("rescueTemp", PERWAPI.PrimitiveType.Object); int ExceptionTemp = context.CreateLocal("exceptionTemp", PERWAPI.PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); context.StartBlock(Clause.Try); { expr.GenCode(context); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(endLabel); } } PERWAPI.TryBlock tryBlock = context.EndTryBlock(); context.StartBlock(Clause.Catch); { PERWAPI.CILLabel stdErrLabel = context.NewLabel(); context.stloc(ExceptionTemp); context.ldloc(ExceptionTemp); context.ldfld(Runtime.RubyException.parent); context.isinst(Runtime.StandardErrorRef); context.brtrue(stdErrLabel); context.ldloc(ExceptionTemp); context.throwOp(); context.CodeLabel(stdErrLabel); rescue.GenCode(context); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(endLabel); } } context.EndCatchBlock(Runtime.RubyExceptionRef, tryBlock); context.CodeLabel(endLabel); context.ldloc(RescueTemp); context.ReleaseLocal(RescueTemp, true); context.ReleaseLocal(ExceptionTemp, true); }