/// <summary> /// Creates the "ExpressionToInfer" instances (=nodes in dependency graph) /// </summary> /// <remarks> /// We are using a dependency graph to ensure that expressions are analyzed in the correct order. /// </remarks> void CreateDependencyGraph(ILNode node) { ILCondition cond = node as ILCondition; if (cond != null) { cond.Condition.ExpectedType = typeSystem.Boolean; } ILWhileLoop loop = node as ILWhileLoop; if (loop != null && loop.Condition != null) { loop.Condition.ExpectedType = typeSystem.Boolean; } ILTryCatchBlock.CatchBlock catchBlock = node as ILTryCatchBlock.CatchBlock; if (catchBlock != null && catchBlock.ExceptionVariable != null && catchBlock.ExceptionType != null && catchBlock.ExceptionVariable.Type == null) { catchBlock.ExceptionVariable.Type = catchBlock.ExceptionType; } ILExpression expr = node as ILExpression; if (expr != null) { ExpressionToInfer expressionToInfer = new ExpressionToInfer(); expressionToInfer.Expression = expr; allExpressions.Add(expressionToInfer); FindNestedAssignments(expr, expressionToInfer); if (expr.Code == ILCode.Stloc && ((ILVariable)expr.Operand).Type == null) assignmentExpressions[(ILVariable)expr.Operand].Add(expressionToInfer); return; } foreach (ILNode child in node.GetChildren()) { CreateDependencyGraph(child); } }
/// <summary> /// For each variable reference, adds <paramref name="direction"/> to the num* dicts. /// Direction will be 1 for analysis, and -1 when removing a node from analysis. /// </summary> void AnalyzeNode(ILNode node, int direction = 1) { ILExpression expr = node as ILExpression; if (expr != null) { ILVariable locVar = expr.Operand as ILVariable; if (locVar != null) { if (expr.Code == ILCode.Stloc) { numStloc[locVar] = numStloc.GetOrDefault(locVar) + direction; } else if (expr.Code == ILCode.Ldloc) { numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + direction; } else if (expr.Code == ILCode.Ldloca) { numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + direction; } else { throw new NotSupportedException(expr.Code.ToString()); } } foreach (ILExpression child in expr.Arguments) AnalyzeNode(child, direction); } else { var catchBlock = node as ILTryCatchBlock.CatchBlock; if (catchBlock != null && catchBlock.ExceptionVariable != null) { numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + direction; } foreach (ILNode child in node.GetChildren()) AnalyzeNode(child, direction); } }
void InferTypes(ILNode node) { ILCondition cond = node as ILCondition; if (cond != null) { InferTypeForExpression(cond.Condition, typeSystem.Boolean, false); } ILWhileLoop loop = node as ILWhileLoop; if (loop != null && loop.Condition != null) { InferTypeForExpression(loop.Condition, typeSystem.Boolean, false); } ILExpression expr = node as ILExpression; if (expr != null) { ILVariable v = expr.Operand as ILVariable; if (v != null && v.IsGenerated && v.Type == null && expr.Code == ILCode.Stloc && !inferredVariables.Contains(v) && HasSingleLoad(v)) { // Don't deal with this node or its children yet, // wait for the expected type to be inferred first. // This happens with the arg_... variables introduced by the ILAst - we skip inferring the whole statement, // and first infer the statement that reads from the arg_... variable. // The ldloc inference will write the expected type to the variable, and the next InferRemainingStores() pass // will then infer this statement with the correct expected type. storedToGeneratedVariables.Add(expr); return; } bool anyArgumentIsMissingType = expr.Arguments.Any(a => a.InferredType == null); if (expr.InferredType == null || anyArgumentIsMissingType) expr.InferredType = InferTypeForExpression(expr, expr.ExpectedType, forceInferChildren: anyArgumentIsMissingType); } foreach (ILNode child in node.GetChildren()) { InferTypes(child); } }
public bool addCreateNewNode(ILNode node, int pos) { if (newBody.ContainsKey (pos)) { return addNewNode (node, maxCodePos+1); } else { return addNewNode (node, pos); } }
public override bool Match(ILNode other) { ILExpression expr = other as ILExpression; if (expr != null && expr.Code == ILCode.Stloc && (!MustBeGenerated || ((ILVariable)expr.Operand).IsGenerated) && Match(this.Arguments, expr.Arguments)) { this.LastMatch = expr; return true; } else { return false; } }
public static void AddILRangesTryPreviousFirst(ILNode prev, ILNode next, ILBlockBase block, IEnumerable<ILRange> ilRanges) { if (prev != null && prev.SafeToAddToEndILRanges) prev.EndILRanges.AddRange(ilRanges); else if (next != null) next.ILRanges.AddRange(ilRanges); else if (prev != null) block.EndILRanges.AddRange(ilRanges); else block.ILRanges.AddRange(ilRanges); }
public bool addNewNode(ILNode node, int pos) { if (newBody.ContainsKey (pos)) { return false; } if (pos > maxCodePos) { maxCodePos = pos; } this.newBody.Add (pos,node); return true; }
public static void AddILRangesToInstruction(ILNode nodeToAddTo, ILNode prev, ILNode next, ILBlockBase block, ILNode removed) { Debug.Assert(nodeToAddTo == prev || nodeToAddTo == next || nodeToAddTo == block); if (nodeToAddTo != null) { if (nodeToAddTo == prev && prev.SafeToAddToEndILRanges) { removed.AddSelfAndChildrenRecursiveILRanges(prev.EndILRanges); return; } else if (nodeToAddTo != null && nodeToAddTo == next) { removed.AddSelfAndChildrenRecursiveILRanges(next.ILRanges); return; } } AddILRangesTryNextFirst(prev, next, block, removed); }
/// <summary> /// Inlines 'expr' into 'next', if possible. /// </summary> public static bool InlineIfPossible(ILExpression expr, ILNode next, ILBlock method) { if (expr.Code != ILCode.Stloc) throw new ArgumentException("expr must be stloc"); // ensure the variable is accessed only a single time if (method.GetSelfAndChildrenRecursive<ILExpression>().Count(e => e != expr && e.Operand == expr.Operand) != 1) return false; ILExpression parent; int pos; if (FindLoadInNext(next as ILExpression, (ILVariable)expr.Operand, out parent, out pos) == true) { parent.Arguments[pos] = expr.Arguments[0]; return true; } return false; }
public virtual ILNode Visit(ILNode node) { if (node == null) return node; var block = node as ILBlock; if (block != null) return VisitBlock(block); var basicBlock = node as ILBasicBlock; if (basicBlock != null) return VisitBasicBlock(basicBlock); var label = node as ILLabel; if (label != null) return VisitLabel(label); var tryCatchBlock = node as ILTryCatchBlock; if (tryCatchBlock != null) return VisitTryCatchBlock(tryCatchBlock); var expression = node as ILExpression; if (expression != null) return VisitExpression(expression); var whileLoop = node as ILWhileLoop; if (whileLoop != null) return VisitWhileLoop(whileLoop); var condition = node as ILCondition; if (condition != null) return VisitCondition(condition); var switchStatement = node as ILSwitch; if (switchStatement != null) return VisitSwitch(switchStatement); var fixedStatement = node as ILFixedStatement; if (fixedStatement != null) return VisitFixedStatement(fixedStatement); throw new NotSupportedException(); }
/// <summary> /// Inlines 'expr' into 'next', if possible. /// </summary> bool InlineIfPossible(ILVariable v, ILExpression inlinedExpression, ILNode next, bool aggressive) { // ensure the variable is accessed only a single time if (numStloc.GetOrDefault(v) != 1) return false; int ldloc = numLdloc.GetOrDefault(v); if (ldloc > 1 || ldloc + numLdloca.GetOrDefault(v) != 1) return false; if (next is ILCondition) next = ((ILCondition)next).Condition; else if (next is ILWhileLoop) next = ((ILWhileLoop)next).Condition; ILExpression parent; int pos; if (FindLoadInNext(next as ILExpression, v, inlinedExpression, out parent, out pos) == true) { if (ldloc == 0) { if (!IsGeneratedValueTypeTemporary((ILExpression)next, parent, pos, v, inlinedExpression)) return false; } else { if (!aggressive && !v.GeneratedByDecompiler && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression)) return false; } // Assign the ranges of the ldloc instruction: if (context.CalculateILRanges) parent.Arguments[pos].AddSelfAndChildrenRecursiveILRanges(inlinedExpression.ILRanges); if (ldloc == 0) { // it was an ldloca instruction, so we need to use the pseudo-opcode 'addressof' so that the types // comes out correctly parent.Arguments[pos] = new ILExpression(ILCode.AddressOf, null, inlinedExpression); } else { parent.Arguments[pos] = inlinedExpression; } return true; } return false; }
public void Message(string msg, ILNode n) { DoMessage(MType.Message, msg, n); }
static bool MatchStFld(ILNode stfld, ILVariable stateMachineVar, out FieldDef field, out ILExpression expr) { field = null; IField fieldRef; ILExpression ldloca; if (!stfld.Match(ILCode.Stfld, out fieldRef, out ldloca, out expr)) return false; field = fieldRef.ResolveFieldWithinSameModule(); return field != null && ldloca.MatchLdloca(stateMachineVar); }
/// <summary> /// Flattens all nested basic blocks, except the the top level 'node' argument /// </summary> void FlattenBasicBlocks(ILNode node) { ILBlock block = node as ILBlock; if (block != null) { List<ILNode> flatBody = new List<ILNode>(); foreach (ILNode child in block.GetChildren()) { FlattenBasicBlocks(child); if (child is ILBasicBlock) { flatBody.AddRange(child.GetChildren()); } else { flatBody.Add(child); } } block.EntryGoto = null; block.Body = flatBody; } else if (node is ILExpression) { // Optimization - no need to check expressions } else if (node != null) { // Recursively find all ILBlocks foreach(ILNode child in node.GetChildren()) { FlattenBasicBlocks(child); } } }
public static bool IsLiteral(this ILNode node) { return(node.Kind == LNodeKind.Literal); }
public static bool IsId(this ILNode node) { return(node.Kind == LNodeKind.Id); }
public JSNode TranslateNode(ILNode node) { Console.Error.WriteLine("Node NYI: {0}", node.GetType().Name); return new JSUntranslatableStatement(node.GetType().Name); }
public static bool IsParenthesizedExpr(this ILNode node) { return(node.Attrs().NodeNamed(CodeSymbols.TriviaInParens) != null); }
public static bool Calls(this ILNode node, Symbol name) { return(node.CallsMin(name, 0)); }
public static bool IsIdNamed(this ILNode node, string name) { var nn = node.Name; return(nn == null ? name == null : nn.Name == name); }
public static bool IsIdNamed(this ILNode node, Symbol name) { return(node.Name == name); }
public static NodeStyle BaseStyle(this ILNode node) { return(node.Style & NodeStyle.BaseStyleMask); }
public static bool IsTrivia(this ILNode node) { return(CodeSymbols.IsTriviaSymbol(node.Name)); }
public static NegListSlice <ILNode> Args(this ILNode node) { return(new NegListSlice <ILNode>(node, 0, System.Math.Max(node.Max + 1, 0))); }
public static void Warning(string msg, ILNode node, params object[] o) { ErrorContext.Out.Warning(msg, node, o); }
public static bool HasSpecialName(this ILNode node) { return(LNode.IsSpecialName(node.Name)); }
public static NegListSlice <ILNode> Attrs(this ILNode node) { int min = node.Min; return(new NegListSlice <ILNode>(node, min, -1 - min)); }
public static bool HasAttrs(this ILNode node) { return(node.Min < -1); }
public static int ArgCount(this ILNode node) { return(node.Max + 1); }
public static ILNode AttrNamed(this ILNode node, Symbol name) { return(node.Attrs().NodeNamed(name)); }
IEnumerable<Statement> TransformNode(ILNode node) { if (node is ILLabel) { yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name }; } else if (node is ILExpression) { List<ILRange> ilRanges = ((ILExpression)node).GetILRanges(); AstNode codeExpr = TransformExpression((ILExpression)node); if (codeExpr != null) { codeExpr = codeExpr.WithAnnotation(ilRanges); if (codeExpr is Ast.Expression) { yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr }; } else if (codeExpr is Ast.Statement) { yield return (Ast.Statement)codeExpr; } else { throw new Exception(); } } } else if (node is ILWhileLoop) { ILWhileLoop ilLoop = (ILWhileLoop)node; if (ilLoop.PreLoopLabel != null) yield return TransformNode(ilLoop.PreLoopLabel).Single(); WhileStatement whileStmt = new WhileStatement() { Condition = ilLoop.Condition != null ? MakeBranchCondition(ilLoop.Condition) : new PrimitiveExpression(true), EmbeddedStatement = TransformBlock(ilLoop.BodyBlock) }; yield return whileStmt; if (ilLoop.PostLoopGoto != null) yield return (Statement)TransformExpression(ilLoop.PostLoopGoto); } else if (node is ILCondition) { ILCondition conditionalNode = (ILCondition)node; yield return new Ast.IfElseStatement { Condition = MakeBranchCondition(conditionalNode.Condition), TrueStatement = TransformBlock(conditionalNode.TrueBlock), FalseStatement = TransformBlock(conditionalNode.FalseBlock) }; } else if (node is ILSwitch) { ILSwitch ilSwitch = (ILSwitch)node; SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition.Arguments[0]) }; for (int i = 0; i < ilSwitch.CaseBlocks.Count; i++) { SwitchSection section = new SwitchSection(); section.CaseLabels.Add(new CaseLabel() { Expression = new PrimitiveExpression(i) }); section.Statements.Add(TransformBlock(ilSwitch.CaseBlocks[i])); switchStmt.SwitchSections.Add(section); } yield return switchStmt; if (ilSwitch.DefaultGoto != null) yield return (Statement)TransformExpression(ilSwitch.DefaultGoto); } else if (node is ILTryCatchBlock) { ILTryCatchBlock tryCatchNode = ((ILTryCatchBlock)node); var tryCatchStmt = new Ast.TryCatchStatement(); tryCatchStmt.TryBlock = TransformBlock(tryCatchNode.TryBlock); foreach (var catchClause in tryCatchNode.CatchBlocks) { tryCatchStmt.CatchClauses.Add( new Ast.CatchClause { Type = AstBuilder.ConvertType(catchClause.ExceptionType), VariableName = catchClause.ExceptionVariable == null ? null : catchClause.ExceptionVariable.Name, Body = TransformBlock(catchClause) }); } if (tryCatchNode.FinallyBlock != null) tryCatchStmt.FinallyBlock = TransformBlock(tryCatchNode.FinallyBlock); yield return tryCatchStmt; } else if (node is ILBlock) { yield return TransformBlock((ILBlock)node); } else if (node is ILComment) { yield return new CommentStatement(((ILComment)node).Text).WithAnnotation(((ILComment)node).ILRanges); } else { throw new Exception("Unknown node type"); } }
/// <summary>Converts <see cref="ILNode"/> to <see cref="LNode"/> recursively. /// If the specified node is already an <see cref="LNode"/>, this method simply /// does a cast.</summary> public static LNode ToLNode(ILNode node) { return(node is LNode ? (LNode)node : ToLNodeCore(node)); }
static bool IsVariableReset(ILNode expr, ILVariable variable) { object unused; ILExpression ldloca; return expr.Match(ILCode.Initobj, out unused, out ldloca) && ldloca.MatchLdloca(variable); }
public void Print(ILNode node, StringBuilder target, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null) { Les2Printer.Print(node, target, sink, mode, options); }
bool MatchStateAssignment(ILNode stfld, out int stateID) { // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(stateId)) stateID = 0; IField fieldRef; ILExpression target, val; if (stfld.Match(ILCode.Stfld, out fieldRef, out target, out val)) { return fieldRef.ResolveFieldWithinSameModule() == stateField && target.MatchThis() && val.Match(ILCode.Ldc_I4, out stateID); } return false; }
private void ProcessMethodDecencies(InterMethod method, ILNode node, List <InterGenericArgument> genericArgs) { if (node is ILBlock) { ILBlock block = node as ILBlock; foreach (ILNode n in block.Body) { ProcessMethodDecencies(method, n, genericArgs); } } else if (node is ILBasicBlock) { ILBasicBlock block = node as ILBasicBlock; foreach (ILNode n in block.Body) { ProcessMethodDecencies(method, n, genericArgs); } } else if (node is ILTryCatchBlock) { ILTryCatchBlock block = node as ILTryCatchBlock; foreach (ILNode n in block.TryBlock.Body) { ProcessMethodDecencies(method, n, genericArgs); } if (block.FaultBlock != null) { foreach (ILNode n in block.FaultBlock.Body) { ProcessMethodDecencies(method, n, genericArgs); } } if (block.FinallyBlock != null) { foreach (ILNode n in block.FinallyBlock.Body) { ProcessMethodDecencies(method, n, genericArgs); } } foreach (var catchBlock in block.CatchBlocks) { ((IResolver)this).Resolve(catchBlock.ExceptionType, genericArgs); ProcessMethodDecencies(method, catchBlock, genericArgs); } } else if (node is ILExpression) { ILExpression e = node as ILExpression; foreach (var n in e.Arguments) { ProcessMethodDecencies(method, n, genericArgs); } if ((e.Code == ILCode.Mkrefany) || (e.Code == ILCode.Refanyval)) { ((IResolver)this).Resolve(ClassNames.SystemTypedReference.ClassName); } if (e.Code == ILCode.Refanytype) { ((IResolver)this).Resolve(ClassNames.SystemTypedReference.ClassName); ((IResolver)this).Resolve(ClassNames.SystemRuntimeTypeHandle.ClassName); } if (e.Code == ILCode.Arglist) { ((IResolver)this).Resolve(ClassNames.SystemRuntimeArgumentHandle.ClassName); } if (e.Code.IsExternalRealization()) { ((IResolver)this).Resolve(ClassNames.CIL2JavaVESInstructions.ClassName); } if (e.Code == ILCode.Ldc_Decimal) { ((IResolver)this).Resolve(ClassNames.SystemDecimal.ClassNames); } if (e.Code == ILCode.Ldtoken) { if (e.Operand is TypeReference) { ((IResolver)this).Resolve(ClassNames.SystemRuntimeTypeHandle.ClassName); } else if (e.Operand is FieldReference) { ((IResolver)this).Resolve(ClassNames.SystemRuntimeFieldHandle.ClassName); } else if (e.Operand is MethodReference) { ((IResolver)this).Resolve(ClassNames.SystemRuntimeMethodHandle.ClassName); } } if (e.Operand is ILVariable) { ((IResolver)this).Resolve(((ILVariable)e.Operand).Type, genericArgs); } if (e.Operand is TypeReference) { ((IResolver)this).Resolve((TypeReference)e.Operand, genericArgs); } if (e.Operand is MethodReference) { ((IResolver)this).Resolve((MethodReference)e.Operand, genericArgs); } if (e.Operand is FieldReference) { InterField fld = ((IResolver)this).Resolve((FieldReference)e.Operand, genericArgs); bool needAccessor = false; if ((fld.IsPrivate) && (fld.DeclaringType != method.DeclaringType)) { needAccessor = true; } else if ((fld.IsProtected) && (fld.DeclaringType != method.DeclaringType) && (!method.DeclaringType.IsSuper(fld.DeclaringType))) { needAccessor = true; } if (needAccessor) { switch (e.Code) { case ILCode.Ldflda: case ILCode.Ldsflda: if (fld.FieldType.IsValueType) { fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Getter, fld)); } break; case ILCode.Ldfld: case ILCode.Ldsfld: fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Getter, fld)); break; case ILCode.Stfld: case ILCode.Stsfld: fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Setter, fld)); break; } } } InterType expected = null; InterType inferred = null; if (e.ExpectedType != null) { expected = ((IResolver)this).Resolve(e.ExpectedType, genericArgs); } if (e.InferredType != null) { inferred = ((IResolver)this).Resolve(e.InferredType, genericArgs); } if ((expected != null) && (expected.IsInterface) && (inferred != null) && (inferred.IsArray)) { ((IResolver)this).Resolve(ClassNames.ArraysInterfaceAdapterTypeName, new List <InterGenericArgument>() { new InterGenericArgument(GenericArgumentOwnerType.Type, 0, inferred.ElementType) }); } } else if (node is ILWhileLoop) { ILWhileLoop loop = node as ILWhileLoop; ProcessMethodDecencies(method, loop.Condition, genericArgs); ProcessMethodDecencies(method, loop.BodyBlock, genericArgs); } else if (node is ILCondition) { ILCondition cond = node as ILCondition; ProcessMethodDecencies(method, cond.Condition, genericArgs); ProcessMethodDecencies(method, cond.TrueBlock, genericArgs); ProcessMethodDecencies(method, cond.FalseBlock, genericArgs); } else if (node is ILSwitch) { ILSwitch sw = node as ILSwitch; ProcessMethodDecencies(method, sw.Condition, genericArgs); foreach (var c in sw.CaseBlocks) { ProcessMethodDecencies(method, c, genericArgs); } } else if (node is ILFixedStatement) { ILFixedStatement fs = node as ILFixedStatement; foreach (var n in fs.Initializers) { ProcessMethodDecencies(method, n, genericArgs); } ProcessMethodDecencies(method, fs.BodyBlock, genericArgs); } }
/// <summary> /// Initializes the state range logic: /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue) /// </summary> void InitStateRanges(ILNode entryPoint) { ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange()); ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue); rangeAnalysisStateVariable = null; }
/// <summary>Associates a node with a range.</summary> /// <remarks>Typically this method is set as the value of /// <see cref="ILNodePrinterOptions.SaveRange"/> so that range info is captured /// while converting a node to text. This class does not need or use the third /// parameter (depth).</remarks> public void SaveRange(ILNode node, IndexRange range, int depth = -1) { _startLocations[range.StartIndex].Add(Pair.Create(node, range.EndIndex)); _endLocations [range.EndIndex].Add(Pair.Create(node, range.StartIndex)); }
public static void Message(this IMessages msg, string str, ILNode n, params object[] o) { msg.Message(string.Format(str, o), n); }
protected JSStatement TranslateStatement(ILNode node) { var translated = TranslateNode(node as dynamic); var statement = translated as JSStatement; if (statement == null) { var expression = (JSExpression)translated; if (expression != null) statement = new JSExpressionStatement(expression); else Console.Error.WriteLine("Warning: Null statement: {0}", node); } return statement; }
public static void Info(string msg, ILNode node, params object[] o) { ErrorContext.Out.Info(msg,node, o); }
static LNode ToLNodeCore(ILNode node) { var attrs = VList<LNode>.Empty; for (int i = node.Min; i < -1; i++) attrs.Add(ToLNodeCore(node[i])); switch (node.Kind) { case LNodeKind.Id: return LNode.Id(attrs, node.Name, node.Range, node.Style); case LNodeKind.Literal: return LNode.Literal(attrs, node.Value, node.Range, node.Style); default: var args = VList<LNode>.Empty; for (int i = 0, max = node.Max; i <= max; i++) args.Add(ToLNodeCore(node[i])); var target = ToLNodeCore(node.Target); return LNode.Call(attrs, target, args, node.Range, node.Style); } }
public static void FatalError(string msg, ILNode node, params object[] o) { ErrorContext.Out.FatalError(msg, node, o); }
/// <summary> /// Get the first expression to be excecuted if the instruction pointer is at the end of the given node /// </summary> ILNode Exit(ILNode node, HashSet<ILNode> visitedNodes) { if (node == null) throw new ArgumentNullException(); ILNode nodeParent = parent[node]; if (nodeParent == null) return null; // Exited main body if (nodeParent is ILBlock) { ILNode nextNode = nextSibling[node]; if (nextNode != null) { return Enter(nextNode, visitedNodes); } else { return Exit(nodeParent, visitedNodes); } } if (nodeParent is ILCondition) { return Exit(nodeParent, visitedNodes); } if (nodeParent is ILTryCatchBlock) { // Finally blocks are completely ignored. // We rely on the fact that try blocks can not be entered. return Exit(nodeParent, visitedNodes); } if (nodeParent is ILSwitch) { return null; // Implicit exit from switch is not allowed } if (nodeParent is ILWhileLoop) { return Enter(nodeParent, visitedNodes); } throw new NotSupportedException(nodeParent.GetType().ToString()); }
protected bool ContainsLabels(ILNode root) { var label = root.GetSelfAndChildrenRecursive<ILLabel>().FirstOrDefault(); return label != null; }
public static int AttrCount(this ILNode node) { return(-node.Min - 1); }
/// <summary>Converts <see cref="ILNode"/> to <see cref="LNode"/> recursively. /// If the specified node is already an <see cref="LNode"/>, this method simply /// does a cast.</summary> public static LNode ToLNode(ILNode node) { return node is LNode ? (LNode)node : ToLNodeCore(node); }
/// <summary> /// Flattens all nested movable blocks, except the the top level 'node' argument /// </summary> void FlattenNestedMovableBlocks(ILNode node) { ILBlock block = node as ILBlock; if (block != null) { List<ILNode> flatBody = new List<ILNode>(); if (block.EntryPoint != null) { flatBody.Add(new ILExpression(OpCodes.Br, block.EntryPoint)); block.EntryPoint = null; } foreach (ILNode child in block.Body) { FlattenNestedMovableBlocks(child); if (child is ILMoveableBlock) { flatBody.AddRange(((ILMoveableBlock)child).Body); } else { flatBody.Add(child); } } block.Body = flatBody; } else if (node is ILExpression) { // Optimization - no need to check expressions } else if (node != null) { // Recursively find all ILBlocks foreach(ILNode child in node.GetChildren()) { FlattenNestedMovableBlocks(child); } } }
/// <summary> /// Get the first expression to be excecuted if the instruction pointer is at the start of the given node. /// Try blocks may not be entered in any way. If possible, the try block is returned as the node to be executed. /// </summary> ILNode Enter(ILNode node, HashSet<ILNode> visitedNodes) { if (node == null) throw new ArgumentNullException(); if (!visitedNodes.Add(node)) return null; // Infinite loop ILLabel label = node as ILLabel; if (label != null) { return Exit(label, visitedNodes); } ILExpression expr = node as ILExpression; if (expr != null) { if (expr.Code == ILCode.Br || expr.Code == ILCode.Leave) { ILLabel target = (ILLabel)expr.Operand; // Early exit - same try-block if (GetParents(expr).OfType<ILTryCatchBlock>().FirstOrDefault() == GetParents(target).OfType<ILTryCatchBlock>().FirstOrDefault()) return Enter(target, visitedNodes); // Make sure we are not entering any try-block var srcTryBlocks = GetParents(expr).OfType<ILTryCatchBlock>().Reverse().ToList(); var dstTryBlocks = GetParents(target).OfType<ILTryCatchBlock>().Reverse().ToList(); // Skip blocks that we are already in int i = 0; while(i < srcTryBlocks.Count && i < dstTryBlocks.Count && srcTryBlocks[i] == dstTryBlocks[i]) i++; if (i == dstTryBlocks.Count) { return Enter(target, visitedNodes); } else { ILTryCatchBlock dstTryBlock = dstTryBlocks[i]; // Check that the goto points to the start ILTryCatchBlock current = dstTryBlock; while(current != null) { foreach(ILNode n in current.TryBlock.Body) { if (n is ILLabel) { if (n == target) return dstTryBlock; } else if (!n.Match(ILCode.Nop)) { current = n as ILTryCatchBlock; break; } } } return null; } } else if (expr.Code == ILCode.Nop) { return Exit(expr, visitedNodes); } else if (expr.Code == ILCode.LoopOrSwitchBreak) { ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch); return Exit(breakBlock, new HashSet<ILNode>() { expr }); } else if (expr.Code == ILCode.LoopContinue) { ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop); return Enter(continueBlock, new HashSet<ILNode>() { expr }); } else { return expr; } } ILBlock block = node as ILBlock; if (block != null) { if (block.EntryGoto != null) { return Enter(block.EntryGoto, visitedNodes); } else if (block.Body.Count > 0) { return Enter(block.Body[0], visitedNodes); } else { return Exit(block, visitedNodes); } } ILCondition cond = node as ILCondition; if (cond != null) { return cond.Condition; } ILWhileLoop loop = node as ILWhileLoop; if (loop != null) { if (loop.Condition != null) { return loop.Condition; } else { return Enter(loop.BodyBlock, visitedNodes); } } ILTryCatchBlock tryCatch = node as ILTryCatchBlock; if (tryCatch != null) { return tryCatch; } ILSwitch ilSwitch = node as ILSwitch; if (ilSwitch != null) { return ilSwitch.Condition; } throw new NotSupportedException(node.GetType().ToString()); }
/// <summary>Method to add Nodes in the StructureViewer to the seperated ToolBoxNode</summary> /// <param name="extNode">ILNode to be added</param> public void AddToolboxNode(ILNode extNode) { structureViever.AddToolboxNode(extNode); }
IEnumerable<ILNode> GetParents(ILNode node) { ILNode current = node; while(true) { current = parent[current]; if (current == null) yield break; yield return current; } }
public static bool IsCall(this ILNode node) { return(node.Kind == LNodeKind.Call); }
IEnumerable<Statement> TransformNode(ILNode node) { if (node is ILLabel) { yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name }; } else if (node is ILExpression) { List<ILRange> ilRanges = ILRange.OrderAndJoint(node.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges)); AstNode codeExpr = TransformExpression((ILExpression)node); if (codeExpr != null) { codeExpr = codeExpr.WithAnnotation(ilRanges); if (codeExpr is Ast.Expression) { yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr }; } else if (codeExpr is Ast.Statement) { yield return (Ast.Statement)codeExpr; } else { throw new Exception(); } } } else if (node is ILWhileLoop) { ILWhileLoop ilLoop = (ILWhileLoop)node; WhileStatement whileStmt = new WhileStatement() { Condition = ilLoop.Condition != null ? (Expression)TransformExpression(ilLoop.Condition) : new PrimitiveExpression(true), EmbeddedStatement = TransformBlock(ilLoop.BodyBlock) }; yield return whileStmt; } else if (node is ILCondition) { ILCondition conditionalNode = (ILCondition)node; bool hasFalseBlock = conditionalNode.FalseBlock.EntryGoto != null || conditionalNode.FalseBlock.Body.Count > 0; yield return new Ast.IfElseStatement { Condition = (Expression)TransformExpression(conditionalNode.Condition), TrueStatement = TransformBlock(conditionalNode.TrueBlock), FalseStatement = hasFalseBlock ? TransformBlock(conditionalNode.FalseBlock) : null }; } else if (node is ILSwitch) { ILSwitch ilSwitch = (ILSwitch)node; SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition) }; foreach (var caseBlock in ilSwitch.CaseBlocks) { SwitchSection section = new SwitchSection(); if (caseBlock.Values != null) { section.CaseLabels.AddRange(caseBlock.Values.Select(i => new CaseLabel() { Expression = AstBuilder.MakePrimitive(i, ilSwitch.Condition.InferredType) })); } else { section.CaseLabels.Add(new CaseLabel()); } section.Statements.Add(TransformBlock(caseBlock)); switchStmt.SwitchSections.Add(section); } yield return switchStmt; } else if (node is ILTryCatchBlock) { ILTryCatchBlock tryCatchNode = ((ILTryCatchBlock)node); var tryCatchStmt = new Ast.TryCatchStatement(); tryCatchStmt.TryBlock = TransformBlock(tryCatchNode.TryBlock); foreach (var catchClause in tryCatchNode.CatchBlocks) { if (catchClause.ExceptionVariable == null && (catchClause.ExceptionType == null || catchClause.ExceptionType.MetadataType == MetadataType.Object)) { tryCatchStmt.CatchClauses.Add(new Ast.CatchClause { Body = TransformBlock(catchClause) }); } else { tryCatchStmt.CatchClauses.Add( new Ast.CatchClause { Type = AstBuilder.ConvertType(catchClause.ExceptionType), VariableName = catchClause.ExceptionVariable == null ? null : catchClause.ExceptionVariable.Name, Body = TransformBlock(catchClause) }); } } if (tryCatchNode.FinallyBlock != null) tryCatchStmt.FinallyBlock = TransformBlock(tryCatchNode.FinallyBlock); if (tryCatchNode.FaultBlock != null) { CatchClause cc = new CatchClause(); cc.Body = TransformBlock(tryCatchNode.FaultBlock); cc.Body.Add(new ThrowStatement()); // rethrow tryCatchStmt.CatchClauses.Add(cc); } yield return tryCatchStmt; } else if (node is ILFixedStatement) { ILFixedStatement fixedNode = (ILFixedStatement)node; FixedStatement fixedStatement = new FixedStatement(); foreach (ILExpression initializer in fixedNode.Initializers) { Debug.Assert(initializer.Code == ILCode.Stloc); ILVariable v = (ILVariable)initializer.Operand; fixedStatement.Variables.Add( new VariableInitializer { Name = v.Name, Initializer = (Expression)TransformExpression(initializer.Arguments[0]) }.WithAnnotation(v)); } fixedStatement.Type = AstBuilder.ConvertType(((ILVariable)fixedNode.Initializers[0].Operand).Type); fixedStatement.EmbeddedStatement = TransformBlock(fixedNode.BodyBlock); yield return fixedStatement; } else if (node is ILBlock) { yield return TransformBlock((ILBlock)node); } else { throw new Exception("Unknown node type"); } }
public Either <Symbol, ILogMessage> TryPrint(ILNode literal, out StringBuilder sb) { sb = new StringBuilder(); return(TryPrint(literal, sb)); }