private static Stack <StackUseDefinition> GetStackAfter(OpExpression opInfo) { var newStack = new Stack <StackUseDefinition>( opInfo.StackBefore ?? Enumerable.Empty <StackUseDefinition>()); if (opInfo.InstructionPopCount == null) { newStack.Clear(); } else { var popCount = opInfo.InstructionPopCount; //if (opInfo.IsHandlerStart) // popCount--; for (var i = 0; i < popCount; i++) { newStack.Pop(); } } for (var i = 0; i < opInfo.PushCount; i++) { newStack.Push( new StackUseDefinition { Definitions = new List <Node> { opInfo } }); } return(newStack); }
private string MakeWhereStr(OpExpression opExpression) { if (opExpression == null) { return(""); } StringBuilder sb = new StringBuilder(); switch ((int)opExpression.joinOp) { //叶子 case 0: sb.Append(opExpression.Condition.key) .Append(GetOpStr((int)opExpression.Condition.op)) .Append(ToSqlString(opExpression.Condition.value)); break; case 1: sb.Append(" ( ").Append(MakeWhereStr(opExpression.Left)).Append(" And ").Append(MakeWhereStr(opExpression.Right)).Append(" ) "); break; case 2: sb.Append(" ( ").Append(MakeWhereStr(opExpression.Left)).Append(" Or ").Append(MakeWhereStr(opExpression.Right)).Append(" ) "); break; } return(sb.ToString()); }
public JSExpression Translate(OpExpression node) { var arg = node.Arguments.Single(); var expr = ProcessInternal(arg); var argIsInt64 = arg.ResultType == context.SystemTypes.Int64 || arg.ResultType == context.SystemTypes.UInt64; if (node.Instruction.OpCode.Name == "conv.u8") { if (argIsInt64) { return(expr); } else { return(JSFactory.Call(JSFactory.Identifier("BLR", "conv_u8"), expr)); } } if (node.Instruction.OpCode.Name == "conv.i8") { if (argIsInt64) { return(expr); } else { return(JSFactory.Call(JSFactory.Identifier("BLR", "conv_i8"), expr)); } } if (argIsInt64) { if (node.Instruction.OpCode.Name == "conv.r.un") { return(JSFactory.Call(JSFactory.Identifier("BLR", "to_number_unsigned"), expr)); } else { return(JSFactory.Call(JSFactory.Identifier("BLR", "to_number_signed"), expr)); } } if (IsIntegerType(node.ResultType)) { return(JSFactory.Truncate(expr)); } else { return(expr); } }
private static IEnumerable <span> GetExpressionSpans(Block block) { OpExpression start = null; OpExpression prev = null; foreach (var node in block.Ast) { var expr = node as OpExpression; if (expr == null || expr.PushCount > 1) { start = null; } else if (expr.PushCount == 0) { if (start != null && prev != null && start != expr) { yield return new span { from = start, to = expr } } ; start = null; } else if (expr.StackBefore.Count == 0) { if (start != null && prev != null && start != prev) { yield return new span { from = start, to = prev } } ; start = expr; } prev = expr; } if (start != null && prev != null && start != prev) { yield return new span { from = start, to = prev } } ; } } }
private void ProcessOp(OpExpression rootOp, OpExpression op) { rootOp.RequireFieldInitTypes = new List <Type>(); var opc = op.Instruction.OpCode.Name; var i = opc.IndexOf("."); var opc_ = i > 0 ? opc.Substring(0, i) : opc; switch (opc_) { case "call": case "callvirt": var mi = (MethodBase)op.Instruction.Data; if (mi.DeclaringType.IsInterface) { rootOp.RequireFieldInitTypes.Add(mi.DeclaringType); } break; case "ldsfld": case "stsfld": rootOp.RequireFieldInitTypes.Add(((MemberInfo)op.Instruction.Data).DeclaringType); break; case "newobj": var t = ((MemberInfo)op.Instruction.Data).DeclaringType; while (t != null) { rootOp.RequireFieldInitTypes.Add(t); t = t.BaseType; } break; default: break; } foreach (var subop in op.Arguments.OfType <OpExpression>()) { ProcessOp(rootOp, subop); } }
private IKVM.Reflection.Type InferBinaryArithmeticType(OpExpression op) { var int32s = new[] { types.Char, types.Sbyte, types.Int32, types.Byte, types.UInt32 }; var int64s = new[] { types.Int64, types.UInt64 }; var a = op.Arguments.First().ResultType; var b = op.Arguments.Last().ResultType; if (int32s.Contains(a)) { a = types.Int32; } if (int32s.Contains(b)) { b = types.Int32; } if (int64s.Contains(a)) { a = types.Int64; } if (int64s.Contains(b)) { b = types.Int64; } if (a == b) { return(a); } else if (op.Instruction.OpCode.Name.StartsWith("sh")) { return(a); } else { throw new NotSupportedException(); } }
private static bool UpdateTargetStack(Stack <StackUseDefinition> newStack, OpExpression target) { var stackList = newStack.Reverse().ToList(); var changed = false; if (target.StackBefore == null) { target.StackBefore = stackList .Select( n => new StackUseDefinition { Usage = target, Definitions = n.Definitions.ToList() }) .ToList(); changed = true; } else { // Merging stacks described in ECMA - 335, III.1.8.1.3 for (var i = 0; i < stackList.Count; i++) { var oldDef = target.StackBefore[i]; var newDef = stackList[i]; var beforeCount = oldDef.Definitions.Count; oldDef.Definitions = oldDef.Definitions.Concat(newDef.Definitions).Distinct().ToList(); if (oldDef.Definitions.Count != beforeCount) { changed = true; } } } return(changed); }
private static void UpdateTargets(Stack <OpExpression> processStack, OpExpression opInfo, Stack <StackUseDefinition> newStack) { foreach (var target in opInfo.Targets) { if (target.IsHandlerStart) { newStack.Push(new StackUseDefinition { Definitions = new List <Node> { new ExceptionNode() } }); } if (UpdateTargetStack(newStack, target)) { processStack.Push(target); } if (target.IsHandlerStart) { newStack.Pop(); } } }
private List <OpExpression> CreateOpInfos(CilMethod method) { var ilOps = new OpInstructionReader(method.MethodBody.GetILAsByteArray(), method.Resolver); var opInfos = new List <OpExpression>(); var prefixes = new List <OpInstruction>(); foreach (var op in ilOps.Process()) { if (op.OpCode.OpCodeType == OpCodeType.Prefix) { prefixes.Add(op); continue; } OpExpression opx; if (op.OpCode.Name.StartsWith("call")) { opx = new CallNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data)); } else if (op.OpCode.Name.StartsWith("ldftn")) { opx = new LoadFunctionNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data)); } else { opx = new OpExpression(op, prefixes, GetPopCount(method, op), GetPushCount(method, op)); } opInfos.Add(opx); prefixes = new List <OpInstruction>(); } foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (current, next) => new { current, next })) { pairs.current.Next = pairs.next; } foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (prev, current) => new { current, prev })) { pairs.current.Prev = pairs.prev; } var body = method.MethodBody; var handlers = body != null ? body.ExceptionHandlingClauses : new List <ExceptionHandlingClause>(); // Create targets foreach (var opInfo in opInfos) { if (opInfo.Instruction.OpCode.Name == "switch") { var i = opInfo.Instruction; var switchEndPosition = 1 + i.Position + i.Size; var target = opInfos.First(p => p.Position == switchEndPosition); opInfo.Targets.Add(target); foreach (var targetOffset in (int[])i.Data) { var targetPosition = 1 + i.Position + i.Size + targetOffset; target = opInfos.First(f2 => f2.Position == targetPosition); opInfo.Targets.Add(target); } } else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Branch) { var position = GetTargetPosition(opInfo.Instruction); opInfo.Targets = new List <OpExpression> { opInfos.First(i => i.Position == position) }; } else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Cond_Branch) { var position = GetTargetPosition(opInfo.Instruction); opInfo.Targets = new List <OpExpression> { opInfos.First(i => i.Position == position) }; if (opInfo.Next != null) { opInfo.Targets.Add(opInfo.Next); } } else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Throw) { // nothing } else { if (opInfo.Next != null) { opInfo.Targets.Add(opInfo.Next); } } if (opInfo.Next != null) { foreach (var handler in handlers.Where(t => t.TryOffset == opInfo.Next.Position)) { if (handler.Flags != ExceptionHandlingClauseOptions.Clause && handler.Flags != ExceptionHandlingClauseOptions.Finally) { continue; } var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset); opInfo.Targets.Add(handlerStart); } } foreach (var target in opInfo.Targets) { target.Targeting.Add(opInfo); } } foreach (var handler in handlers) { if (handler.Flags != ExceptionHandlingClauseOptions.Clause) { continue; } var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset); handlerStart.IsHandlerStart = true; } return(opInfos); }
private IKVM.Reflection.Type InferType(CilMethod method, OpExpression op) { var opc = op.Instruction.OpCode.Name; var i = opc.IndexOf("."); var opc_ = i > 0 ? opc.Substring(0, i) : opc; var methodBody = method.MethodBody; switch (opc_) { case "add": case "and": return(InferBinaryArithmeticType(op)); case "box": return(types.Object); case "call": case "callvirt": { var mb = ((MethodBase)op.Instruction.Data); var mi = mb as MethodInfo; if (mi != null) { return(mi.ReturnType); } return(null); } case "castclass": return((IKVM.Reflection.Type)op.Instruction.Data); case "ceq": case "cgt": case "clt": return(types.Boolean); // err... should this be int? case "conv": var t = opc == "conv.i1" ? types.Int32 : opc == "conv.i2" ? types.Int32 : opc == "conv.i4" ? types.Int32 : opc == "conv.i8" ? types.Int64 : opc == "conv.r4" ? types.Single : opc == "conv.r8" ? types.Double : opc == "conv.u1" ? types.UInt32 : opc == "conv.u2" ? types.UInt32 : opc == "conv.u4" ? types.UInt32 : opc == "conv.u8" ? types.UInt64 : opc == "conv.i" ? types.Int32 : opc == "conv.u" ? types.Int32 : opc == "conv.r.un" ? types.Single : null; return(t); case "div": case "div.un": return(InferBinaryArithmeticType(op)); case "dup": return(op.Targeting.First().ResultType); case "endfinally": return(null); case "initobj": return((Type)op.Instruction.Data); case "isinst": return((Type)op.Instruction.Data); case "ldarg": { var id = ""; if (op.Instruction.Data != null) { id = op.Instruction.Data.ToString(); } else { id = opc.Replace(".s", ".").Replace(".", "").Substring("ldarg".Length); } var idx = int.Parse(id); if (false == method.ReflectionMethod.IsStatic) { if (idx == 0) { if (method.ReflectionMethod.DeclaringType.IsValueType) { return(types.ManagedPointer.MakeGenericType(method.ReflectionMethod.DeclaringType)); } else { return(method.ReflectionMethod.DeclaringType); } } else { idx -= 1; } } return(method.ReflectionMethod.GetParameters()[idx].ParameterType); } case "ldarga": { var idxStr = ""; if (op.Instruction.Data != null) { idxStr = op.Instruction.Data.ToString(); } idxStr = opc.Replace(".s", ".").Replace(".", "").Substring("ldarga".Length) + idxStr; var idx = int.Parse(idxStr); if (method.ReflectionMethod.IsStatic == false) { idx--; } var args = method.ReflectionMethod.GetParameters(); var type = args[idx].ParameterType; return(types.ManagedPointer.MakeGenericType(type)); } case "ldc": if (opc.StartsWith("ldc.i4")) { return(types.Int32); } else if (opc.StartsWith("ldc.i8")) { return(types.Int64); } else if (opc.StartsWith("ldc.r8")) { return(types.Double); } else { return(types.Single); } case "ldelem": switch (opc) { case "ldelem": return((Type)op.Instruction.Data); case "ldelem.ref": return(op.Arguments.First().ResultType.GetElementType()); //throw new NotImplementedException(); // array element type case "ldelem.i1": return(types.Sbyte); case "ldelem.i2": return(types.Int16); case "ldelem.i4": return(types.Int32); case "ldelem.i8": return(types.Int64); case "ldelem.u1": return(types.Byte); case "ldelem.u2": return(types.UInt16); case "ldelem.u4": return(types.UInt32); case "ldelem.u8": return(types.UInt64); case "ldelem.r4": return(types.Single); case "ldelem.r8": return(types.Double); case "ldelem.i": return(types.Int32); default: throw new NotSupportedException(); } case "ldelema": { var type = (Type)op.Instruction.Data; return(types.ManagedPointer.MakeGenericType(type)); } case "ldfld": return(((FieldInfo)op.Instruction.Data).FieldType); case "ldftn": return(types.IntPtr); case "ldlen": return(types.UInt32); case "ldloc": { var id = ""; if (op.Instruction.Data != null) { id = op.Instruction.Data.ToString(); } id = opc.Substring(5).Replace(".s", ".").Replace(".", "") + id; return(methodBody.LocalVariables[int.Parse(id)].LocalType); } case "ldloca": { var id = ""; if (op.Instruction.Data != null) { id = op.Instruction.Data.ToString(); } var idx = int.Parse(opc.Substring(5).Replace("a.", ".").Replace(".s", ".").Replace(".", "") + id); var type = methodBody.LocalVariables[idx].LocalType; return(types.ManagedPointer.MakeGenericType(type)); } case "ldnull": return(types.Null); case "ldobj": return((Type)op.Instruction.Data); case "ldsfld": return(((FieldInfo)op.Instruction.Data).FieldType); case "ldflda": { var fieldType = ((FieldInfo)op.Instruction.Data).FieldType; return(types.ManagedPointer.MakeGenericType(fieldType)); } case "ldstr": return(types.String); case "ldtoken": return(types.Object); //universe.GetType("System.Reflection.MemberInfo"); case "mul": return(InferBinaryArithmeticType(op)); case "neg": return(op.Arguments.First().ResultType); case "newarr": return(((Type)op.Instruction.Data).MakeArrayType()); case "newobj": return(((ConstructorInfo)op.Instruction.Data).DeclaringType); case "nop": return(null); case "or": return(InferBinaryArithmeticType(op)); case "pop": return(null); case "rem": case "rem.un": return(InferBinaryArithmeticType(op)); case "ret": return(null); case "shl": case "shr": case "shr.un": return(InferBinaryArithmeticType(op)); case "stelem": case "stind": case "stloc": case "stfld": case "stsfld": return(null); case "sub": return(InferBinaryArithmeticType(op)); case "throw": return(null); case "unbox": return((Type)op.Instruction.Data); default: return(null); } }
public JSExpression Translate(OpExpression node) { var opc = node.Instruction.OpCode.Name; var i = opc.IndexOf("."); var opc_ = i > 0 ? opc.Substring(0, i) : opc; var isUnsigned = opc.Contains(".un"); switch (opc_) { case "ceq": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_Equality")); } else { return(new JSConditionalExpression { Condition = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "===" }, TrueValue = new JSNumberLiteral { Value = 1 }, FalseValue = new JSNumberLiteral { Value = 0 } }); } case "cgt": if (opc == "cgt.un" && node.Arguments.Last().ResultType == context.SystemTypes.Null) { // we should consider using Number(0) instead of 'null' return(new JSConditionalExpression { Condition = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "!==" }, TrueValue = new JSNumberLiteral { Value = 1 }, FalseValue = new JSNumberLiteral { Value = 0 } }); } else { if (IsUInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "UInt64_GreaterThan")); } else if (IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "Int64_GreaterThan")); } else { return(new JSConditionalExpression { Condition = new JSBinaryExpression { Left = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.First())), Right = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.Last())), Operator = ">" }, TrueValue = new JSNumberLiteral { Value = 1 }, FalseValue = new JSNumberLiteral { Value = 0 } }); } } case "clt": if (IsUInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "UInt64_LessThan")); } else if (IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "Int64_LessThan")); } else { return(new JSConditionalExpression { Condition = new JSBinaryExpression { Left = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.First())), Right = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.Last())), Operator = "<" }, TrueValue = new JSNumberLiteral { Value = 1 }, FalseValue = new JSNumberLiteral { Value = 0 } }); } default: throw new NotSupportedException(node.Instruction.OpCode.Name); } }
public bool Contains(OpExpression frame) { return(frame.Instruction.Position < To && frame.Position >= From); }
private IEnumerable <Type> FindTypes(CilMethod method, OpExpression op) { if (method.ReflectionMethod == method.ReflectionMethod.DeclaringType.Assembly.EntryPoint) { yield return(context.SystemTypes.ValueType); } var opc = op.Instruction.OpCode.Name; var i = opc.IndexOf("."); var opc_ = i > 0 ? opc.Substring(0, i) : opc; switch (opc_) { case "castclass": case "initobj": case "isinst": case "newarr": case "box": var d = (Type)op.Instruction.Data; yield return(d); break; case "call": case "callvirt": var mi = (MethodBase)op.Instruction.Data; if (mi.IsGenericMethod) { foreach (var g in mi.GetGenericArguments()) { yield return(g); } } if (mi.DeclaringType.IsInterface) { yield return(mi.DeclaringType); } break; case "ldtoken": var type = op.Instruction.Data as Type; if (type != null) { yield return(type); } yield break; case "ldsfld": case "stsfld": case "newobj": yield return(((MemberInfo)op.Instruction.Data).DeclaringType); break; default: break; } }
public JSExpression Translate(OpExpression node) { var opc = node.Instruction.OpCode.Name; var i = opc.IndexOf("."); var opc_ = i > 0 ? opc.Substring(0, i) : opc; switch (opc_) { case "add": if (node.ResultType == context.SystemTypes.UInt64 || node.ResultType == context.SystemTypes.Int64) { return(JSFactory.Call( JSFactory.Identifier("asm0", "XInt64_Addition"), ProcessInternal(node.Arguments.First()), ProcessInternal(node.Arguments.Last()))); } else { var expr = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "+" } as JSExpression; if (IsIntegerType(node.ResultType)) { expr = JSFactory.Truncate(expr); } return(expr); } case "and": if (node.ResultType == context.SystemTypes.UInt64 || node.ResultType == context.SystemTypes.Int64) { return(JSFactory.Call( JSFactory.Identifier("asm0", "XInt64_BitwiseAnd"), ProcessInternal(node.Arguments.First()), ProcessInternal(node.Arguments.Last()))); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "&" }); } case "div": case "div.un": if (IsUInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "UInt64_Division")); } else if (IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "Int64_Division")); } else { var divExpression = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "/" }; if (IsIntegerType(node.ResultType)) { return(JSFactory.Truncate(divExpression)); } else { return(divExpression); } } case "mul": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_Multiplication")); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "*" }); } case "neg": if (node.ResultType == context.SystemTypes.Int64) { return(JSFactory.Call( JSFactory.Identifier("asm0", "Int64_UnaryNegation"), ProcessInternal(node.Arguments.First()))); } else { return(new JSUnaryExpression { Operator = "-", Operand = ProcessInternal(node.Arguments.Single()) }); } case "not": if (node.ResultType == context.SystemTypes.Int64) { return(JSFactory.Call( JSFactory.Identifier("asm0", "XInt64_OnesComplement"), ProcessInternal(node.Arguments.First()))); } else { return(new JSUnaryExpression { Operator = "~", Operand = ProcessInternal(node.Arguments.Single()) }); } case "or": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_BitwiseOr")); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "|" }); } case "rem": case "rem.un": if (IsUInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "UInt64_Modulus")); } else if (IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "Int64_Modulus")); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "%" }); } case "shl": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_LeftShift")); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "<<" }); } case "shr": if (IsUInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "UInt64_RightShift")); } else if (IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "Int64_RightShift")); } else { return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = ">>" }); } case "shr.un": return(new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = ">>>" }); case "sub": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_Subtraction")); } else { var expr = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "-" } as JSExpression; if (IsIntegerType(node.ResultType)) { expr = JSFactory.Truncate(expr); } return(expr); } case "xor": if (IsUInt64Operation(node) || IsInt64Operation(node)) { return(CreateXInt64BinaryOperation(node, "XInt64_ExclusiveOr")); } else { var expr = new JSBinaryExpression { Left = ProcessInternal(node.Arguments.First()), Right = ProcessInternal(node.Arguments.Last()), Operator = "^" } as JSExpression; return(expr); } default: throw new NotSupportedException(node.Instruction.OpCode.Name); } }
protected void MarkTargetForUpdate(OpExpression target) { processStack.Push(target); }
protected virtual void Process(OpExpression opInfo) { }