private Instruction[] ParseInstructions(XmlNode opList, ILProcessor proc) { List <Instruction> ret = new List <Instruction>(); List <QueuedGenerator> queuedGenerators = new List <QueuedGenerator>(); foreach (XmlNode opNode in opList.ChildNodes) { if (opNode is XmlComment) { continue; } //if (opNode.Attributes["name"] == null) // continue; IInstructionGenerator instGen = ParseOpcode(opNode); Instruction inst = instGen.Generate(proc, ret); if (inst == null) { inst = proc.Create(OpCodes.Nop); queuedGenerators.Add(new QueuedGenerator(instGen, ret.Count)); } ret.Add(inst); } foreach (QueuedGenerator curGen in queuedGenerators) { Instruction newInstr = curGen.generator.Generate(proc, ret); if (newInstr == null) { throw new ArgumentOutOfRangeException("xmlpatchers.xml : Instruction reference out of range!"); } Instruction prevInstr = ret[curGen.index]; prevInstr.OpCode = newInstr.OpCode; prevInstr.Operand = newInstr.Operand; } return(ret.ToArray()); }
public OpCodeInfo(byte opCode, string assemblerKeyword, byte instructionSize, byte numberOfArguments, IInstructionGenerator instructionGenerator = null) { this.OpCode = opCode; this.AssemblerKeyword = assemblerKeyword; this.InstructionSize = instructionSize; this.NumberOfArguments = numberOfArguments; if (instructionSize > 1 && instructionGenerator == null) throw new ArgumentNullException("instructionGenerator", string.Format("[{0}]: instructionGenerator is required when the instruction size is greater than 1.", assemblerKeyword)); this.InstructionGenerator = instructionGenerator; }
/// <summary> /// Generates code for a .text instruction in the file. /// </summary> /// <param name="fileName">The source file name.</param> /// <param name="asmLine">The line to parse.</param> /// <param name="objFile">The object file that will be written to.</param> /// <param name="currAlignment">The current specified alignment of the file. Unused for .text parsers.</param> public void GenerateCodeForSegment(string fileName, LineData asmLine, BasicObjectFile objFile, int currAlignment) { // scan to the first instruction. // this could share the same line as a label, so split on ':' and ',' string[] tokenizedStr = asmLine.Text.Split(new char[] { ',', ':', ' ' }, StringSplitOptions.RemoveEmptyEntries); bool foundInstruction = false; string instructionToken = string.Empty; for (int i = 0; i < tokenizedStr.Length && !foundInstruction; ++i) { string token = tokenizedStr[i].Trim(); // we found our instruction. build a string from this token // to the end of the array. if (m_ParserFac.IsInstruction(token)) { foundInstruction = true; instructionToken = token; } } if (foundInstruction) { // first, validate that the instruction is not the last token in the string. // try to parse the instruction parameters // get the substring starting at the index of the next character after the instruction string instSubstring = asmLine.Text.Substring(asmLine.Text.IndexOf(instructionToken) + instructionToken.Length); //split the substring at the comma to get the instruction parameters. string[] argTokens = instSubstring.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); // trim whitespace from the beginning and end of each token. argTokens = argTokens.Apply((str) => str.Trim()).ToArray(); // find the parser for the instruction. IInstructionGenerator parser = m_ParserFac.GetProcessorForInstruction(instructionToken); // beq instructions should (hopefully) not generate multiple instructions.. IEnumerable <int> generatedInstructions = parser.GenerateCodeForInstruction(m_CurrTextAddress, argTokens); var srcInfo = new SourceLineInformation(fileName, asmLine.LineNum, m_CurrTextAddress, asmLine.Text); objFile.AddSourceInformation(srcInfo); foreach (int generatedInstruction in generatedInstructions) { objFile.AddInstruction(generatedInstruction); m_CurrTextAddress += CommonConstants.BASE_INSTRUCTION_SIZE_BYTES; } } else { // if not an instruction (may be a symbol) // preprocesor instruction shouldn't bring us here. // make sure the user is not typing garbage. string symStr = tokenizedStr[0]; if (!m_SymTbl.ContainsSymbol(symStr)) { throw new AssemblyException(asmLine.LineNum, "Unknown instruction \"" + asmLine.Text + "\" found."); } } }
private bool Matches(MethodDefinition method, XmlNode opList) { ILProcessor proc = method.Body.GetILProcessor(); List <Instruction> instrs = new List <Instruction>(method.Body.Instructions); int i = 0; foreach (XmlNode opNode in opList.ChildNodes) { if (opNode is XmlComment) { continue; } int index; XmlAttribute indexAttribute = opNode.Attributes["index"]; if (indexAttribute == null) { index = i++; } else { index = Int32.Parse(indexAttribute.Value); if (index < 0) { index += instrs.Count; } i = index + 1; } if (index >= instrs.Count || index < 0) { return(false); } //if (opNode.Attributes["name"] == null) // continue; IInstructionGenerator instGen = ParseOpcode(opNode); if (instGen.GetOpCode() != instrs[index].OpCode) { return(false); } if (instGen.HasOperand() != (instrs[index].Operand != null)) { continue; } Instruction inst = instGen.Generate(proc, instrs); if (inst == null) { return(false); } object methodOp = instrs[index].Operand; object compareOp = inst.Operand; Type methodOpType = instrs[index].Operand.GetType(); if (methodOpType != inst.Operand.GetType()) { return(false); } switch (methodOpType.Name) { case "Byte": if ((Byte)methodOp != (Byte)compareOp) { return(false); } break; case "SByte": if ((SByte)methodOp != (SByte)compareOp) { return(false); } break; case "Int32": if ((Int32)methodOp != (Int32)compareOp) { return(false); } break; case "Int64": if ((Int64)methodOp != (Int64)compareOp) { return(false); } break; case "Single": if ((Single)methodOp != (Single)compareOp) { return(false); } break; case "Double": if ((Double)methodOp != (Double)compareOp) { return(false); } break; case "String": if (!methodOp.Equals(compareOp)) { return(false); } break; case "Instruction": if (methodOp != compareOp) { return(false); } break; case "TypeReference": if (!((TypeReference)methodOp).FullName.Equals(((TypeReference)compareOp).FullName)) { return(false); } break; case "FieldReference": if (!((FieldReference)methodOp).FullName.Equals(((FieldReference)compareOp).FullName)) { return(false); } break; case "MethodReference": if (!((MethodReference)methodOp).ToString().Equals(((MethodReference)compareOp).ToString())) //ToString includes the method { return(false); } break; default: logger.Warning("XmlPatches : Nobody told me how to compare two " + methodOpType.Name + "s!"); break; } } return(true); }
public QueuedGenerator(IInstructionGenerator generator, int index) { this.generator = generator; this.index = index; }