ILExpression MakeGoTo(LabelRangeMapping mapping, int state) { foreach (var pair in mapping) { if (pair.Value.Contains(state)) { return(new ILExpression(ILCode.Br, pair.Key)); } } throw new SymbolicAnalysisFailedException(); }
void CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength, LabelRangeMapping result, bool onlyInitialLabels) { for (int i = pos; i < bodyLength; i++) { ILLabel label = body[i] as ILLabel; if (label != null) { result.Add(new KeyValuePair<ILLabel, StateRange>(label, ranges[label])); } else { ILTryCatchBlock tryCatchBlock = body[i] as ILTryCatchBlock; if (tryCatchBlock != null) { CreateLabelRangeMapping(tryCatchBlock.TryBlock.Body, 0, tryCatchBlock.TryBlock.Body.Count, result, true); } else if (onlyInitialLabels) { break; } } } }
List<ILNode> ConvertBody(List<ILNode> body, int startPos, int bodyLength, LabelRangeMapping mapping) { List<ILNode> newBody = new List<ILNode>(); // Copy all instructions from the old body to newBody. for (int pos = startPos; pos < bodyLength; pos++) { ILTryCatchBlock tryCatchBlock = body[pos] as ILTryCatchBlock; ILExpression expr = body[pos] as ILExpression; if (expr != null && expr.Code == ILCode.Leave && expr.Operand == exitLabel) { ILVariable awaiterVar; FieldDef awaiterField; int targetStateID; HandleAwait(newBody, out awaiterVar, out awaiterField, out targetStateID); MarkAsGeneratedVariable(awaiterVar); newBody.Add(new ILExpression(ILCode.Await, null, new ILExpression(ILCode.Ldloca, awaiterVar))); newBody.Add(MakeGoTo(mapping, targetStateID)); } else if (tryCatchBlock != null) { ILTryCatchBlock newTryCatchBlock = new ILTryCatchBlock(); var tryBody = tryCatchBlock.TryBlock.Body; if (tryBody.Count == 0) throw new SymbolicAnalysisFailedException(); StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(tryBody[0], StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar); int tryBodyLength = tryBody.Count; int posInTryBody = rangeAnalysis.AssignStateRanges(tryBody, tryBodyLength); rangeAnalysis.EnsureLabelAtPos(tryBody, ref posInTryBody, ref tryBodyLength); var mappingInTryBlock = rangeAnalysis.CreateLabelRangeMapping(tryBody, posInTryBody, tryBodyLength); var newTryBody = ConvertBody(tryBody, posInTryBody, tryBodyLength, mappingInTryBlock); newTryBody.Insert(0, MakeGoTo(mappingInTryBlock, initialState)); // If there's a label at the beginning of the state dispatcher, copy that if (posInTryBody > 0 && tryBody.FirstOrDefault() is ILLabel) newTryBody.Insert(0, tryBody.First()); newTryCatchBlock.TryBlock = new ILBlock(newTryBody); newTryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(tryCatchBlock.CatchBlocks); newTryCatchBlock.FaultBlock = tryCatchBlock.FaultBlock; if (tryCatchBlock.FinallyBlock != null) newTryCatchBlock.FinallyBlock = new ILBlock(ConvertFinally(tryCatchBlock.FinallyBlock.Body)); newBody.Add(newTryCatchBlock); } else { newBody.Add(body[pos]); } } return newBody; }
ILExpression MakeGoTo(LabelRangeMapping mapping, int state) { foreach (var pair in mapping) { if (pair.Value.Contains(state)) return new ILExpression(ILCode.Br, pair.Key); } throw new SymbolicAnalysisFailedException(); }
public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength) { LabelRangeMapping result = new LabelRangeMapping(); CreateLabelRangeMapping(body, pos, bodyLength, result, false); return result; }