/// <summary> /// Since we need to use ourselves. /// </summary> /// <param name="method"></param> /// <param name="instruction"></param> /// <param name="indentStart"></param> /// <returns></returns> public static string ParseInstruction(MethodDefinition method, Instruction instruction, int indentStart) { var opcode = instruction.OpCode; string output = ""; //output += AssemblyHelper.Indent("// {0}: {1} {2}", indentStart, instruction.Offset, instruction.OpCode, instruction.Operand) + Environment.NewLine; if (InstructionHelper.IsBranchConditional(opcode.Code)) { output += Indent(GetIfStatement(method, instruction), indentStart) + Environment.NewLine; output += ParseInstruction(method, instruction.Operand as Instruction, indentStart + 1); } // Check if the instruction is for // storing a value onto a variable if (InstructionHelper.IsStore(opcode.Code)) { output += Indent(GetStoreLocation(method, instruction) + " = " + GetValueOf(method, instruction.Previous) + ";", indentStart) + Environment.NewLine; } // Check if we want to return the method // And if there is any value we want to return. else if (opcode.Code == Code.Ret) { if (InstructionHelper.IsLoad(instruction.Previous.OpCode.Code)) { output += Indent("return " + GetValueOf(method, instruction.Previous) + ";", indentStart) + Environment.NewLine; } else { output += Indent("return;", indentStart) + Environment.NewLine; } } return(output); }
public static string GetIfStatement(MethodDefinition method, Instruction instruction) { var target = ""; var ifStatement = "if("; var prev = instruction.Previous; if (InstructionHelper.IsLoad(prev.OpCode.Code)) { target = GetValueOf(method, prev); } if (InstructionHelper.IsBranchOnFalse(instruction.OpCode.Code)) { ifStatement += "!"; } return(ifStatement + target + ")"); }
public static string GetConditionalStatement(MethodDefinition method, Instruction instruction) { var code = instruction.OpCode.Code; var val2 = instruction.Previous; var val1 = val2.Previous; if (InstructionHelper.IsEqualTo(code)) { return(GetValueOf(method, val1) + " == " + GetValueOf(method, val2)); } else if (InstructionHelper.IsLessThan(code)) { return(GetValueOf(method, val1) + " < " + GetValueOf(method, val2)); } else { return(GetValueOf(method, val1) + " > " + GetValueOf(method, val2)); // IsGreaterThan } }
/// <summary> /// This function will return the name of the variable, argument, etc /// that we want to store our value into. /// </summary> /// <param name="method"></param> /// <param name="instruction"></param> /// <returns></returns> public static string GetStoreLocation(MethodDefinition method, Instruction instruction) { var code = instruction.OpCode.Code; if (instruction.Operand != null && !InstructionHelper.IsStoreN(code)) { return(instruction.Operand.ToString()); } if (InstructionHelper.IsStoreLocalVariable(code)) { if (InstructionHelper.IsStoreN(code)) { /* Not yet implemented. */ } else { var index = InstructionHelper.GetCodeIndex(code); return(GetVariableName(method.Body.Variables[index])); } } if (InstructionHelper.IsStoreArgument(code)) { if (InstructionHelper.IsStoreN(code)) { return(instruction.Operand.ToString()); } else { var index = InstructionHelper.GetCodeIndex(code); return(method.Parameters[index].Name); } } return(""); }
/// <summary> /// This function will return a string, representing the values grabbed from the instruction /// </summary> /// <param name="instruction"></param> /// <returns></returns> public static string GetValueOf(MethodDefinition method, Instruction instruction) { var code = instruction.OpCode.Code; // If this is a conditional instruction. lets return the value of that. if (InstructionHelper.IsConditional(instruction.OpCode.Code)) { return(GetConditionalStatement(method, instruction)); } // Check if we are trying to load a value // Can be, Load a field, load a constant value, argument // variable and more. if (InstructionHelper.IsLoad(code)) { // Check if we want to return a null value if (InstructionHelper.IsLoadNull(instruction.OpCode.Code)) { return("null"); } // For now, we will settle with just handling integers. // We will have to add more if checks later to support // strings, variables, etc. if (InstructionHelper.IsLoadInteger(code)) { // In case the integer is bigger than 4 // We will need to get the value from the // operand instead of the "index". if (InstructionHelper.IsLoadN(code)) { return(instruction.Operand.ToString()); } else { // The GetCodeIndex will return the value used from // the constant load. For instance ldc.i4.4 will return // the value 4, ldc.i4.3 will return value 3. Etc. return(InstructionHelper.GetCodeIndex(code).ToString()); } } // Check if we want to load a string // if so, then return the value from the operand. if (InstructionHelper.IsLoadString(code)) { return("\"" + instruction.Operand + "\""); } // If we want to load a local variable. // So be it! if (InstructionHelper.IsLoadLocalVariable(code)) { if (InstructionHelper.IsLoadN(code)) { var targetVariable = instruction.Operand as VariableDefinition; return(GetVariableName(targetVariable)); } else { var index = InstructionHelper.GetCodeIndex(code); return(GetVariableName(method.Body.Variables[index])); } } // If we want to load the value of a argument // Then this is necessary. if (InstructionHelper.IsLoadArgs(code)) { if (InstructionHelper.IsLoadN(code)) { return(instruction.Operand.ToString()); } else { var index = InstructionHelper.GetCodeIndex(code); if (method.IsConstructor) { index--; } return(method.Parameters[index].Name); } } } // If our instructions are to call a method if (InstructionHelper.IsCallMethod(code)) { // We will need to grab the information of that specific method // By casting the Operand into a MethodDefinition. var callingMethod = instruction.Operand as MethodDefinition; // Note: We are not managing any parameters yet. return(callingMethod.Name + "()"); } // Return a empty value if we can't determine what we want to return. return(""); }