/// <summary> /// Is the given any of binary operations. /// </summary> public static bool IsBinaryOperation(this AstCode code) { switch (code) { case AstCode.Add: case AstCode.Add_Ovf: case AstCode.Add_Ovf_Un: case AstCode.Sub: case AstCode.Sub_Ovf: case AstCode.Sub_Ovf_Un: case AstCode.Mul: case AstCode.Mul_Ovf: case AstCode.Mul_Ovf_Un: case AstCode.Div: case AstCode.Div_Un: case AstCode.Rem: case AstCode.Rem_Un: case AstCode.And: case AstCode.Or: case AstCode.Xor: case AstCode.Shl: case AstCode.Shr: case AstCode.Shr_Un: return(true); default: return(false); } }
/// <summary> /// Get a dex if-test opcode for the given code /// </summary> internal static RCode ToIfTest(this AstCode code) { switch (code) { case AstCode.Cle: return(RCode.If_le); case AstCode.Cle_Un: return(RCode.If_le); case AstCode.Clt: return(RCode.If_lt); case AstCode.Clt_Un: return(RCode.If_lt); case AstCode.Ceq: return(RCode.If_eq); case AstCode.Cne: return(RCode.If_ne); case AstCode.Cgt: return(RCode.If_gt); case AstCode.Cgt_Un: return(RCode.If_gt); case AstCode.Cge: return(RCode.If_ge); case AstCode.Cge_Un: return(RCode.If_ge); case AstCode.__Beq: return(RCode.If_eq); case AstCode.__Bne_Un: return(RCode.If_ne); case AstCode.__Ble: case AstCode.__Ble_Un: return(RCode.If_le); case AstCode.__Blt: case AstCode.__Blt_Un: return(RCode.If_lt); case AstCode.__Bgt: case AstCode.__Bgt_Un: return(RCode.If_gt); case AstCode.__Bge: case AstCode.__Bge_Un: return(RCode.If_ge); default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
/// <summary> /// Convert condition to branch/zero. /// /// </summary> public static AstCode ToBranchZ(this AstCode code) { switch (code) { case AstCode.Cle: case AstCode.Cle_Un: return(AstCode.BrIfLe); case AstCode.Clt: case AstCode.Clt_Un: return(AstCode.BrIfLt); case AstCode.Ceq: return(AstCode.BrIfEq); case AstCode.Cne: return(AstCode.BrIfNe); case AstCode.Cgt: case AstCode.Cgt_Un: return(AstCode.BrIfGt); case AstCode.Cge: case AstCode.Cge_Un: return(AstCode.BrIfGe); default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
private static bool IsEqualsBranchOrComparison(AstCode code) { return(code == AstCode.Ceq || code == AstCode.Cne || code == AstCode.Brtrue || code == AstCode.Brfalse || code == AstCode.BrIfNe || code == AstCode.BrIfEq || code == AstCode.__Beq || code == AstCode.__Beq || code == AstCode.__Bne_Un || code == AstCode.__Bne_Un); }
/// <summary> /// Convert the result of the given node to uint8/uint16 if needed. /// </summary> private static void Convert(AstExpression node, AstCode convertCode, XTypeReference expectedType) { // Copy load expression var clone = new AstExpression(node); // Convert node node.Code = convertCode; node.SetArguments(clone); node.Operand = null; node.SetType(expectedType); }
private static void Convert(AstExpression node, AstCode convertCode, XTypeReference expectedType) { // Copy load expression var clone = new AstExpression(node); // Convert node node.Code = convertCode; node.SetArguments(clone); node.Operand = null; node.SetType(expectedType); }
/// <summary> /// Match expression with given code and one argument. /// </summary> public static bool Match(this AstNode node, AstCode code, out AstExpression arg) { List <AstExpression> args; if (node.Match(code, out args) && args.Count == 1) { arg = args[0]; return(true); } arg = null; return(false); }
/// <summary> /// Match basic block ending with an expression with code code and one argument, followed by a branch. /// </summary> public static bool MatchLastAndBr <T>(this AstBasicBlock bb, AstCode code, out T operand, out AstExpression arg, out AstLabel brLabel) { if (bb.Body.ElementAtOrDefault(bb.Body.Count - 2).Match(code, out operand, out arg) && bb.Body.LastOrDefault().Match(AstCode.Br, out brLabel)) { return(true); } operand = default(T); arg = null; brLabel = null; return(false); }
/// <summary> /// Match expression with given code and no arguments. /// </summary> public static bool Match <T>(this AstNode node, AstCode code, out T operand) { var expr = node as AstExpression; if ((expr != null) && (expr.Prefixes == null) && (expr.Code == code) && (expr.Arguments.Count == 0)) { operand = (T)expr.Operand; return(true); } operand = default(T); return(false); }
/// <summary> /// Match basic block with one label followed by an expression with code code and one argument. /// </summary> public static bool MatchSingle <T>(this AstBasicBlock bb, AstCode code, out T operand, out AstExpression arg) { if (bb.Body.Count == 2 && bb.Body[0] is AstLabel && bb.Body[1].Match(code, out operand, out arg)) { return(true); } operand = default(T); arg = null; return(false); }
public AstExpression(ISourceLocation sourceLocation, AstCode code, object operand, params AstExpression[] args) : base(sourceLocation) { if (operand is AstExpression) { throw new ArgumentException("operand"); } Code = code; Operand = operand; Arguments = new List <AstExpression>(args); ILRanges = new List <InstructionRange>(1); }
/// <summary> /// Match expression with given code and zero or more arguments. /// </summary> public static bool Match(this AstNode node, AstCode code, out List <AstExpression> args) { var expr = node as AstExpression; if ((expr != null) && (expr.Prefixes == null) && (expr.Code == code)) { Debug.Assert(expr.Operand == null); args = expr.Arguments; return(true); } args = null; return(false); }
/// <summary> /// Match basic block with one label followed by an expression with code code and one argument, followed by a branch. /// </summary> public static bool MatchSingleAndBr <T>(this AstBasicBlock bb, AstCode code, out T operand, out AstExpression arg, out AstLabel brLabel) { if (bb.Body.Count == 3 && bb.Body[0] is AstLabel && bb.Body[1].Match(code, out operand, out arg) && bb.Body[2].Match(AstCode.Br, out brLabel)) { return(true); } operand = default(T); arg = null; brLabel = null; return(false); }
/// <summary> /// Match expression with given code and two arguments. /// </summary> public static bool Match <T>(this AstNode node, AstCode code, out T operand, out AstExpression arg1, out AstExpression arg2) { List <AstExpression> args; if (node.Match(code, out operand, out args) && args.Count == 2) { arg1 = args[0]; arg2 = args[1]; return(true); } arg1 = null; arg2 = null; return(false); }
/// <summary> /// Match expression with given code and zero or more arguments. /// </summary> public static bool Match <T>(this AstNode node, AstCode code, out T operand, out List <AstExpression> args) { var expr = node as AstExpression; if ((expr != null) && (expr.Prefixes == null) && (expr.Code == code)) { operand = (T)expr.Operand; args = expr.Arguments; return(true); } operand = default(T); args = null; return(false); }
/// <summary> /// Is the given any of the call codes. /// </summary> public static bool IsCall(this AstCode code) { switch (code) { case AstCode.Call: case AstCode.Calli: case AstCode.CallIntf: case AstCode.Callvirt: case AstCode.CallSpecial: return(true); default: return(false); } }
/// <summary> /// Reverses the code, taking account float/double NaN comparisons /// </summary> private static AstCode ReverseCode(AstCode code, XTypeReference type) { bool isFlt = type.IsDouble() || type.IsFloat(); if (!isFlt) { return(code.Reverse()); } switch (code) { case AstCode.Ceq: return(AstCode.Cne); case AstCode.Cne: return(AstCode.Ceq); case AstCode.Cle: return(AstCode.Cgt_Un); case AstCode.Cle_Un: return(AstCode.Cgt); case AstCode.Clt: return(AstCode.Cge_Un); case AstCode.Clt_Un: return(AstCode.Cge); case AstCode.Cgt: return(AstCode.Cle_Un); case AstCode.Cgt_Un: return(AstCode.Cle); case AstCode.Cge: return(AstCode.Clt_Un); case AstCode.Cge_Un: return(AstCode.Clt); default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
private static bool CanPullComparisonUp(AstCode code, XTypeReference arg1, XTypeReference arg2, PullTarget target) { if (arg1 == null || arg2 == null) { return(false); } bool isReference = arg1.IsDexObject() && arg1.IsDexObject(); if (!isReference && !arg1.IsSame(arg2)) { return(false); } if (target == PullTarget.Comparison) { return(true); } if (arg1.Is(XTypeReferenceKind.Float)) { return(false); } if (arg1.IsDexWide()) { return(false); } bool isEq = IsEqualsBranchOrComparison(code); if (isEq) { return(true); } bool isUnsigned = arg1.IsUInt16() || arg1.IsUInt32(); // TODO: check if we really have to exclude unsigned. if (isReference || isUnsigned) { return(false); } return(true); }
/// <summary> /// Create a single bytecode. /// </summary> private ByteCode CreateByteCode(Instruction inst, AstCode code, object operand, int popCount, int pushCount, Category category, XTypeReference type = null) { var next = codeAttr.GetNext(inst); var byteCode = new ByteCode { Category = category, Offset = inst.Offset, EndOffset = (next != null) ? next.Offset : codeAttr.Code.Length, Code = code, Operand = operand, PopCount = popCount, PushCount = pushCount, SourceLocation = new SourceLocation(codeAttr, inst), Type = type }; return(byteCode); }
/// <summary> /// Is the given code a Cxx comparision code that requires an integer? /// </summary> public static bool IsIntegerOnlyCompare(this AstCode code) { switch (code) { case AstCode.Cle: case AstCode.Cle_Un: case AstCode.Clt: case AstCode.Clt_Un: case AstCode.Cgt: case AstCode.Cgt_Un: case AstCode.Cge: case AstCode.Cge_Un: return(true); default: return(false); } }
/// <summary> /// Reverse conditions /// </summary> public static AstCode Reverse(this AstCode code) { switch (code) { case AstCode.Cle: return(AstCode.Cgt); case AstCode.Cle_Un: return(AstCode.Cgt_Un); case AstCode.Clt: return(AstCode.Cge); case AstCode.Clt_Un: return(AstCode.Cge_Un); case AstCode.Ceq: return(AstCode.Cne); case AstCode.Cne: return(AstCode.Ceq); case AstCode.Cgt: return(AstCode.Cle); case AstCode.Cgt_Un: return(AstCode.Cle_Un); case AstCode.Cge: return(AstCode.Clt); case AstCode.Cge_Un: return(AstCode.Clt_Un); case AstCode.CIsNull: return(AstCode.CIsNotNull); case AstCode.CIsNotNull: return(AstCode.CIsNull); default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
private static void MarkReachableForSerialization(ReachableContext context, Instruction arg, MethodBody body) { object operand = arg.Operand; AstCode astCode = (AstCode)arg.OpCode.Code; AstCodeUtil.ExpandMacro(ref astCode, ref operand, body); FieldReference fieldRef; MethodReference methodRef; TypeReference typeRef; VariableReference varRef; ParameterReference paramRef; if ((fieldRef = operand as FieldReference) != null) { fieldRef.FieldType.MarkReachable(context, true); } else if ((methodRef = operand as MethodReference) != null) { if (arg.OpCode == OpCodes.Newobj) { methodRef.DeclaringType.MarkReachable(context, true); } else { methodRef.ReturnType.MarkReachable(context, true); } } else if ((typeRef = operand as TypeReference) != null) { typeRef.SetReachable(context, true); } else if ((paramRef = operand as ParameterReference) != null) { paramRef.ParameterType.MarkReachable(context, true); } else if ((varRef = operand as VariableReference) != null) { varRef.VariableType.MarkReachable(context, true); } // don't know what to do! }
public static bool IsStoreToArray(this AstCode code) { switch (code) { case AstCode.Stelem_Any: case AstCode.Stelem_I: case AstCode.Stelem_I1: case AstCode.Stelem_I2: case AstCode.Stelem_I4: case AstCode.Stelem_I8: case AstCode.Stelem_R4: case AstCode.Stelem_R8: case AstCode.Stelem_Ref: return(true); default: return(false); } }
public static bool IsUnconditionalControlFlow(this AstCode code) { switch (code) { case AstCode.Br: case AstCode.__Br_S: case AstCode.Leave: case AstCode.__Leave_S: case AstCode.Ret: case AstCode.Endfilter: case AstCode.Endfinally: case AstCode.Throw: case AstCode.Rethrow: case AstCode.LoopOrSwitchBreak: return(true); default: return(false); } }
public static bool IsLoadFromArray(this AstCode code) { switch (code) { case AstCode.Ldelem_Any: case AstCode.Ldelem_I: case AstCode.Ldelem_I1: case AstCode.Ldelem_I2: case AstCode.Ldelem_I4: case AstCode.Ldelem_I8: case AstCode.Ldelem_U1: case AstCode.Ldelem_U2: case AstCode.Ldelem_U4: case AstCode.Ldelem_R4: case AstCode.Ldelem_R8: case AstCode.Ldelem_Ref: return(true); default: return(false); } }
/// <summary> /// Convert condition to branch /// </summary> public static AstCode ToBranch(this AstCode code) { switch (code) { case AstCode.Cle: return(AstCode.__Ble); case AstCode.Cle_Un: return(AstCode.__Ble_Un); case AstCode.Clt: return(AstCode.__Blt); case AstCode.Clt_Un: return(AstCode.__Blt_Un); case AstCode.Ceq: return(AstCode.__Beq); case AstCode.Cne: return(AstCode.__Bne_Un); case AstCode.Cgt: return(AstCode.__Bgt); case AstCode.Cgt_Un: return(AstCode.__Bgt_Un); case AstCode.Cge: return(AstCode.__Bge); case AstCode.Cge_Un: return(AstCode.__Bge_Un); default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
public static bool IsConditionalControlFlow(this AstCode code) { switch (code) { case AstCode.__Brfalse_S: case AstCode.__Brtrue_S: case AstCode.__Beq_S: case AstCode.__Bge_S: case AstCode.__Bgt_S: case AstCode.__Ble_S: case AstCode.__Blt_S: case AstCode.__Bne_Un_S: case AstCode.__Bge_Un_S: case AstCode.__Bgt_Un_S: case AstCode.__Ble_Un_S: case AstCode.__Blt_Un_S: case AstCode.Brfalse: case AstCode.Brtrue: case AstCode.__Beq: case AstCode.__Bge: case AstCode.__Bgt: case AstCode.__Ble: case AstCode.__Blt: case AstCode.__Bne_Un: case AstCode.__Bge_Un: case AstCode.__Bgt_Un: case AstCode.__Ble_Un: case AstCode.__Blt_Un: case AstCode.Switch: case AstCode.LookupSwitch: return(true); default: return(false); } }
bool IntroducePostIncrementForVariables(List <AstNode> body, AstExpression expr, int pos) { // Works for variables and static fields/properties // expr = ldloc(i) // stloc(i, add(expr, ldc.i4(1))) // -> // expr = postincrement(1, ldloca(i)) AstVariable exprVar; AstExpression exprInit; if (!(expr.Match(AstCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) { return(false); } //The next expression AstExpression nextExpr = body.ElementAtOrDefault(pos + 1) as AstExpression; if (nextExpr == null) { return(false); } AstCode loadInstruction = exprInit.Code; AstCode storeInstruction = nextExpr.Code; bool recombineVariable = false; // We only recognise local variables, static fields, and static getters with no arguments switch (loadInstruction) { case AstCode.Ldloc: //Must be a matching store type if (storeInstruction != AstCode.Stloc) { return(false); } AstVariable loadVar = (AstVariable)exprInit.Operand; AstVariable storeVar = (AstVariable)nextExpr.Operand; if (loadVar != storeVar) { if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable) { recombineVariable = true; } else { return(false); } } break; case AstCode.Ldsfld: if (storeInstruction != AstCode.Stsfld) { return(false); } if (exprInit.Operand != nextExpr.Operand) { return(false); } break; default: return(false); } AstExpression addExpr = nextExpr.Arguments[0]; int incrementAmount; AstCode incrementCode = GetIncrementCode(addExpr, out incrementAmount); if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) { return(false); } if (recombineVariable) { // Split local variable, unsplit these two instances // replace nextExpr.Operand with exprInit.Operand ReplaceVariables(method, oldVar => oldVar == nextExpr.Operand ? (AstVariable)exprInit.Operand : oldVar); } switch (loadInstruction) { case AstCode.Ldloc: exprInit.Code = AstCode.Ldloca; break; case AstCode.Ldsfld: exprInit.Code = AstCode.Ldsflda; break; } expr.Arguments[0] = new AstExpression(incrementCode, incrementAmount, exprInit); body.RemoveAt(pos + 1); // TODO ILRanges return(true); }
private static bool IsEqualsBranchOrComparison(AstCode code) { return (code == AstCode.Ceq || code == AstCode.Cne || code == AstCode.Brtrue || code == AstCode.Brfalse || code == AstCode.BrIfNe || code == AstCode.BrIfEq || code == AstCode.__Beq || code == AstCode.__Beq || code == AstCode.__Bne_Un|| code == AstCode.__Bne_Un); }
private static bool CanPullComparisonUp(AstCode code, XTypeReference arg1, XTypeReference arg2, PullTarget target) { if (arg1 == null || arg2 == null) return false; bool isReference = arg1.IsDexObject() && arg1.IsDexObject(); if (!isReference && !arg1.IsSame(arg2)) return false; if (target == PullTarget.Comparison) return true; if (arg1.Is(XTypeReferenceKind.Float)) return false; if (arg1.IsDexWide()) return false; bool isEq = IsEqualsBranchOrComparison(code); if (isEq) return true; bool isUnsigned = arg1.IsUInt16() || arg1.IsUInt32(); // TODO: check if we really have to exclude unsigned. if (isReference || isUnsigned) return false; return true; }
/// <summary> /// Reverses the code, taking account float/double NaN comparisons /// </summary> private static AstCode ReverseCode(AstCode code, XTypeReference type) { bool isFlt = type.IsDouble() || type.IsFloat(); if (!isFlt) return code.Reverse(); switch (code) { case AstCode.Ceq: return AstCode.Cne; case AstCode.Cne: return AstCode.Ceq; case AstCode.Cle: return AstCode.Cgt_Un; case AstCode.Cle_Un: return AstCode.Cgt; case AstCode.Clt: return AstCode.Cge_Un; case AstCode.Clt_Un: return AstCode.Cge; case AstCode.Cgt: return AstCode.Cle_Un; case AstCode.Cgt_Un: return AstCode.Cle; case AstCode.Cge: return AstCode.Clt_Un; case AstCode.Cge_Un: return AstCode.Clt; default: throw new ArgumentOutOfRangeException("code", code.ToString()); } }
private static bool IsToEnum(AstCode code) { return code == AstCode.Int_to_enum || code == AstCode.Long_to_enum; }
private static AstExpression LoadGenericArgument(ISourceLocation seqp, XTypeSystem typeSystem, AstCode ldCode, int index, bool loadFromArray) { if (loadFromArray) { var getField = new AstExpression(seqp, ldCode, 0) { ExpectedType = new XArrayType(typeSystem.Type) }; var indexExpr = new AstExpression(seqp, AstCode.Ldc_I4, index) { ExpectedType = typeSystem.Int }; var loadExpr = new AstExpression(seqp, AstCode.Ldelem_Ref, null, getField, indexExpr) { ExpectedType = typeSystem.Type }; return loadExpr; } else { return new AstExpression(seqp, ldCode, index) { ExpectedType = typeSystem.Type }; } }
/// <summary> /// Gets the first prefix of the given code. /// </summary> public AstExpressionPrefix GetPrefix(AstCode code) { var prefixes = Prefixes; return((prefixes != null) ? prefixes.FirstOrDefault(p => p.Code == code) : null); }
AstExpression IntroducePostIncrementForInstanceFields(AstExpression expr) { // stfld(field, ldloc(instance), add(stloc(helperVar, ldfld(field, ldloc(instance))), ldc.i4(1))) // -> stloc(helperVar, postincrement(1, ldflda(field, ldloc(instance)))) // Also works for array elements and pointers: // stelem.any(T, ldloc(instance), ldloc(pos), add(stloc(helperVar, ldelem.any(T, ldloc(instance), ldloc(pos))), ldc.i4(1))) // -> stloc(helperVar, postincrement(1, ldelema(ldloc(instance), ldloc(pos)))) // stobj(T, ldloc(ptr), add(stloc(helperVar, ldobj(T, ldloc(ptr)), ldc.i4(1)))) // -> stloc(helperVar, postIncrement(1, ldloc(ptr))) // callsetter(set_P, ldloc(instance), add(stloc(helperVar, callgetter(get_P, ldloc(instance))), ldc.i4(1))) // -> stloc(helperVar, postIncrement(1, propertyaddress. callgetter(get_P, ldloc(instance)))) if (!(expr.Code == AstCode.Stfld || expr.Code.IsStoreToArray() || expr.Code == AstCode.Stobj)) { return(null); } // Test that all arguments except the last are ldloc (1 arg for fields and pointers, 2 args for arrays) for (int i = 0; i < expr.Arguments.Count - 1; i++) { if (expr.Arguments[i].Code != AstCode.Ldloc) { return(null); } } AstExpression addExpr = expr.Arguments[expr.Arguments.Count - 1]; int incrementAmount; AstCode incrementCode = GetIncrementCode(addExpr, out incrementAmount); AstVariable helperVar; AstExpression initialValue; if (!(incrementAmount != 0 && addExpr.Arguments[0].Match(AstCode.Stloc, out helperVar, out initialValue))) { return(null); } if (expr.Code == AstCode.Stfld) { if (initialValue.Code != AstCode.Ldfld) { return(null); } // There might be two different FieldReference instances, so we compare the field's signatures: FieldReference getField = (FieldReference)initialValue.Operand; FieldReference setField = (FieldReference)expr.Operand; if (!(TypeAnalysis.IsSameType(getField.DeclaringType, setField.DeclaringType) && getField.Name == setField.Name && TypeAnalysis.IsSameType(getField.FieldType, setField.FieldType))) { return(null); } } else if (expr.Code == AstCode.Stobj) { if (!(initialValue.Code == AstCode.Ldobj && initialValue.Operand == expr.Operand)) { return(null); } } else { if (!initialValue.Code.IsLoadFromArray()) { return(null); } } Debug.Assert(expr.Arguments.Count - 1 == initialValue.Arguments.Count); for (int i = 0; i < initialValue.Arguments.Count; i++) { if (!initialValue.Arguments[i].MatchLdloc((AstVariable)expr.Arguments[i].Operand)) { return(null); } } AstExpression stloc = addExpr.Arguments[0]; if (expr.Code == AstCode.Stobj) { stloc.Arguments[0] = new AstExpression(AstCode.PostIncrement, incrementAmount, initialValue.Arguments[0]); } else { stloc.Arguments[0] = new AstExpression(AstCode.PostIncrement, incrementAmount, initialValue); initialValue.Code = (expr.Code == AstCode.Stfld ? AstCode.Ldflda : AstCode.Ldelema); } // TODO: ILRanges? return(stloc); }
private static AstExpression LoadGenericArgument(ISourceLocation seqp, XTypeSystem typeSystem, AstCode ldCode, int index, bool loadFromArray) { if (loadFromArray) { var getField = new AstExpression(seqp, ldCode, 0) { ExpectedType = new XArrayType(typeSystem.Type) }; var indexExpr = new AstExpression(seqp, AstCode.Ldc_I4, index) { ExpectedType = typeSystem.Int }; var loadExpr = new AstExpression(seqp, AstCode.Ldelem_Ref, null, getField, indexExpr) { ExpectedType = typeSystem.Type }; return(loadExpr); } else { return(new AstExpression(seqp, ldCode, index) { ExpectedType = typeSystem.Type }); } }
public static void ExpandMacro(ref AstCode code, ref object operand, MethodBody methodBody) { switch (code) { case AstCode.__Ldarg_0: code = AstCode.__Ldarg; operand = methodBody.GetParameter(0); break; case AstCode.__Ldarg_1: code = AstCode.__Ldarg; operand = methodBody.GetParameter(1); break; case AstCode.__Ldarg_2: code = AstCode.__Ldarg; operand = methodBody.GetParameter(2); break; case AstCode.__Ldarg_3: code = AstCode.__Ldarg; operand = methodBody.GetParameter(3); break; case AstCode.__Ldloc_0: code = AstCode.Ldloc; operand = methodBody.Variables[0]; break; case AstCode.__Ldloc_1: code = AstCode.Ldloc; operand = methodBody.Variables[1]; break; case AstCode.__Ldloc_2: code = AstCode.Ldloc; operand = methodBody.Variables[2]; break; case AstCode.__Ldloc_3: code = AstCode.Ldloc; operand = methodBody.Variables[3]; break; case AstCode.__Stloc_0: code = AstCode.Stloc; operand = methodBody.Variables[0]; break; case AstCode.__Stloc_1: code = AstCode.Stloc; operand = methodBody.Variables[1]; break; case AstCode.__Stloc_2: code = AstCode.Stloc; operand = methodBody.Variables[2]; break; case AstCode.__Stloc_3: code = AstCode.Stloc; operand = methodBody.Variables[3]; break; case AstCode.__Ldarg_S: code = AstCode.__Ldarg; break; case AstCode.__Ldarga_S: code = AstCode.__Ldarga; break; case AstCode.__Starg_S: code = AstCode.__Starg; break; case AstCode.__Ldloc_S: code = AstCode.Ldloc; break; case AstCode.__Ldloca_S: code = AstCode.Ldloca; break; case AstCode.__Stloc_S: code = AstCode.Stloc; break; case AstCode.__Ldc_I4_M1: code = AstCode.Ldc_I4; operand = -1; break; case AstCode.__Ldc_I4_0: code = AstCode.Ldc_I4; operand = 0; break; case AstCode.__Ldc_I4_1: code = AstCode.Ldc_I4; operand = 1; break; case AstCode.__Ldc_I4_2: code = AstCode.Ldc_I4; operand = 2; break; case AstCode.__Ldc_I4_3: code = AstCode.Ldc_I4; operand = 3; break; case AstCode.__Ldc_I4_4: code = AstCode.Ldc_I4; operand = 4; break; case AstCode.__Ldc_I4_5: code = AstCode.Ldc_I4; operand = 5; break; case AstCode.__Ldc_I4_6: code = AstCode.Ldc_I4; operand = 6; break; case AstCode.__Ldc_I4_7: code = AstCode.Ldc_I4; operand = 7; break; case AstCode.__Ldc_I4_8: code = AstCode.Ldc_I4; operand = 8; break; case AstCode.__Ldc_I4_S: code = AstCode.Ldc_I4; operand = (int) (sbyte) operand; break; case AstCode.__Br_S: code = AstCode.Br; break; case AstCode.__Brfalse_S: code = AstCode.Brfalse; break; case AstCode.__Brtrue_S: code = AstCode.Brtrue; break; case AstCode.__Beq_S: code = AstCode.__Beq; break; case AstCode.__Bge_S: code = AstCode.__Bge; break; case AstCode.__Bgt_S: code = AstCode.__Bgt; break; case AstCode.__Ble_S: code = AstCode.__Ble; break; case AstCode.__Blt_S: code = AstCode.__Blt; break; case AstCode.__Bne_Un_S: code = AstCode.__Bne_Un; break; case AstCode.__Bge_Un_S: code = AstCode.__Bge_Un; break; case AstCode.__Bgt_Un_S: code = AstCode.__Bgt_Un; break; case AstCode.__Ble_Un_S: code = AstCode.__Ble_Un; break; case AstCode.__Blt_Un_S: code = AstCode.__Blt_Un; break; case AstCode.__Leave_S: code = AstCode.Leave; break; case AstCode.__Ldind_I: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case AstCode.__Ldind_I1: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.SByte; break; case AstCode.__Ldind_I2: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case AstCode.__Ldind_I4: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case AstCode.__Ldind_I8: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case AstCode.__Ldind_U1: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case AstCode.__Ldind_U2: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt16; break; case AstCode.__Ldind_U4: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt32; break; case AstCode.__Ldind_R4: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case AstCode.__Ldind_R8: code = AstCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Double; break; case AstCode.__Stind_I: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case AstCode.__Stind_I1: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case AstCode.__Stind_I2: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case AstCode.__Stind_I4: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case AstCode.__Stind_I8: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case AstCode.__Stind_R4: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case AstCode.__Stind_R8: code = AstCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Double; break; } }
/// <summary> /// Create a single bytecode. /// </summary> private ByteCode CreateByteCode(Instruction inst, AstCode code, object operand, int popCount, int pushCount, Category category, XTypeReference type = null) { var next = codeAttr.GetNext(inst); var byteCode = new ByteCode { Category = category, Offset = inst.Offset, EndOffset = (next != null) ? next.Offset : codeAttr.Code.Length, Code = code, Operand = operand, PopCount = popCount, PushCount = pushCount, SourceLocation = new SourceLocation(codeAttr, inst), Type = type }; return byteCode; }
/// <summary> /// Default ctor /// </summary> public AstExpressionPrefix(AstCode code, object operand = null) { Code = code; Operand = operand; }