private RLRange BranchToFinally(FinallyTarget target, IEnumerable <RLRange> prefix, ISourceLocation seqp, ref int insIdx) { Debug.Assert(this.HasFinally); Targets.Add(target); var setTarget = new Instruction(RCode.Const) { SequencePoint = seqp }; // operand and register are set later _compiler.instructions.Insert(insIdx++, setTarget); var branch = new Instruction(RCode.Goto, NonException) { SequencePoint = seqp }; _compiler.instructions.Insert(insIdx++, branch); target.SetTarget = setTarget; target.GotoFinally = branch; target.State = this; return(new RLRange(prefix, setTarget, branch, null)); }
public RLRange BranchToFinally_Leave(Instruction insTarget, ref int insIdx) { var target = new FinallyTarget { IsLeave = true, Destination = insTarget }; return(BranchToFinally(target, null, AstNode.NoSource, ref insIdx)); }
public RLRange BranchToFinally_Ret(ref int insIdx) { var target = new FinallyTarget { IsReturn = true }; return(BranchToFinally(target, null, AstNode.NoSource, ref insIdx)); }
public RLRange BranchToFinally_Ret(ISourceLocation sourceLocation, List <RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget { IsReturn = true }; return(BranchToFinally(target, args, sourceLocation, ref insIdx)); }
public RLRange BranchToFinally_FallOut(ISourceLocation sourceLocation, Instruction insTarget, List <RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget { Destination = insTarget, IsFallOut = true }; return(BranchToFinally(target, args, sourceLocation, ref insIdx)); }
public RLRange BranchToFinally_Leave(ISourceLocation sourceLocation, AstLabel labelTarget, List <RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget { IsLeave = true }; _compiler.labelManager.AddResolveAction(labelTarget, ins => target.Destination = ins); return(BranchToFinally(target, args, sourceLocation, ref insIdx)); }
protected bool Equals(FinallyTarget other) { return((IsReturn && other.IsReturn) || (IsFallOut && other.IsFallOut) || Equals(Destination, other.Destination)); }
protected bool Equals(FinallyTarget other) { return (IsReturn && other.IsReturn) || (IsFallOut && other.IsFallOut) || Equals(Destination, other.Destination); }
/// <summary> /// return the first emitted instruction /// </summary> private Instruction TryCatchEmitTargetInstruction(FinallyTarget target, ref int insIdx, FinallyBlockState outerFinallyBlock) { bool emitReturn = outerFinallyBlock == null && target.IsReturn; bool chainToOuterBlock = outerFinallyBlock != null && target.IsReturn; if (target.IsLeave && outerFinallyBlock != null) { // check if the leave leaves the outer finally block as well. if (target.Destination.Index < outerFinallyBlock.FirstInstruction.Index || target.Destination.Index > outerFinallyBlock.LastInstruction.Index) { chainToOuterBlock = true; } } if (emitReturn) { Instruction ret; if (currentMethod.ReturnsVoid) { ret = new Instruction(RCode.Return_void); } else { var retCode = currentMethod.ReturnsDexWide ? RCode.Return_wide : currentMethod.ReturnsDexValue ? RCode.Return : RCode.Return_object; ret = new Instruction(retCode, finallyState.ReturnValueRegister); } instructions.Insert(insIdx++, ret); return(ret); } else if (chainToOuterBlock) { Debug.Assert(outerFinallyBlock != null); int id = target.SetTarget.Code == RCode.Nop ? 0 : (int)target.SetTarget.Operand; RLRange range; if (target.IsReturn) { range = outerFinallyBlock.BranchToFinally_Ret(ref insIdx); } else // IsLeave { range = outerFinallyBlock.BranchToFinally_Leave(target.Destination, ref insIdx); } // This is a little bit hackish. We need to set the operand in the setTarget instruction. if (id == 0) { range.First.ConvertToNop(); } else { range.First.Operand = id; } return(range.First); } else { // goto var insGoto = new Instruction(RCode.Goto, target.Destination); instructions.Insert(insIdx++, insGoto); return(insGoto); } }
public RLRange BranchToFinally_Ret(ref int insIdx) { var target = new FinallyTarget { IsReturn = true }; return BranchToFinally(target, null, AstNode.NoSource, ref insIdx); }
public RLRange BranchToFinally_Leave(Instruction insTarget, ref int insIdx) { var target = new FinallyTarget { IsLeave = true, Destination = insTarget}; return BranchToFinally(target, null, AstNode.NoSource, ref insIdx); }
public RLRange BranchToFinally_Ret(ISourceLocation sourceLocation, List<RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget {IsReturn = true}; return BranchToFinally(target, args, sourceLocation, ref insIdx); }
public RLRange BranchToFinally_FallOut(ISourceLocation sourceLocation, Instruction insTarget, List<RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget {Destination = insTarget, IsFallOut = true}; return BranchToFinally(target, args, sourceLocation, ref insIdx); }
public RLRange BranchToFinally_Leave(ISourceLocation sourceLocation, AstLabel labelTarget, List<RLRange> args) { int insIdx = _compiler.instructions.Count; var target = new FinallyTarget {IsLeave = true }; _compiler.labelManager.AddResolveAction(labelTarget, ins=> target.Destination = ins); return BranchToFinally(target, args, sourceLocation, ref insIdx); }
private RLRange BranchToFinally(FinallyTarget target, IEnumerable<RLRange> prefix, ISourceLocation seqp, ref int insIdx) { Debug.Assert(this.HasFinally); Targets.Add(target); var setTarget = new Instruction(RCode.Const) { SequencePoint = seqp }; // operand and register are set later _compiler.instructions.Insert(insIdx++, setTarget); var branch = new Instruction(RCode.Goto, NonException) {SequencePoint = seqp}; _compiler.instructions.Insert(insIdx++, branch); target.SetTarget = setTarget; target.GotoFinally = branch; target.State = this; return new RLRange(prefix, setTarget, branch, null); }
/// <summary> /// return the first emitted instruction /// </summary> private Instruction TryCatchEmitTargetInstruction(FinallyTarget target, ref int insIdx, FinallyBlockState outerFinallyBlock) { bool emitReturn = outerFinallyBlock == null && target.IsReturn; bool chainToOuterBlock = outerFinallyBlock != null && target.IsReturn; if (target.IsLeave && outerFinallyBlock != null) { // check if the leave leaves the outer finally block as well. if (target.Destination.Index < outerFinallyBlock.FirstInstruction.Index || target.Destination.Index > outerFinallyBlock.LastInstruction.Index) { chainToOuterBlock = true; } } if (emitReturn) { Instruction ret; if (currentMethod.ReturnsVoid) { ret = new Instruction(RCode.Return_void); } else { var retCode = currentMethod.ReturnsDexWide ? RCode.Return_wide : currentMethod.ReturnsDexValue ? RCode.Return : RCode.Return_object; ret = new Instruction(retCode, finallyState.ReturnValueRegister); } instructions.Insert(insIdx++, ret); return ret; } else if (chainToOuterBlock) { Debug.Assert(outerFinallyBlock != null); int id = target.SetTarget.Code == RCode.Nop ? 0 : (int)target.SetTarget.Operand; RLRange range; if (target.IsReturn) range = outerFinallyBlock.BranchToFinally_Ret(ref insIdx); else // IsLeave range = outerFinallyBlock.BranchToFinally_Leave(target.Destination, ref insIdx); // This is a little bit hackish. We need to set the operand in the setTarget instruction. if (id == 0) range.First.ConvertToNop(); else range.First.Operand = id; return range.First; } else { // goto var insGoto = new Instruction(RCode.Goto, target.Destination); instructions.Insert(insIdx++, insGoto); return insGoto; } }