internal void TestPrint() { MemoryStore store = new MemoryStore(); IdentOperand idA = new IdentOperand("A"); TypeOperand typeOp = new TypeOperand(TYPE.INT); NumOperand numA = new NumOperand(10); // We must define the variable prior to using it DefOpCode defOp = new DefOpCode(new Operand[] { idA, typeOp }, store); defOp.Execute(); // Store A Operand[] operands = new Operand[] { idA, numA }; SetOpCode op = new SetOpCode(operands, store); op.Execute(); PrintOpCode printOp = new PrintOpCode(new Operand[] { idA }, store); printOp.Execute(); }
internal void TestSet() { MemoryStore store = new MemoryStore(); IdentOperand id = new IdentOperand("A"); TypeOperand typeOp = new TypeOperand(TYPE.INT); NumOperand num = new NumOperand(10); // We must define the variable prior to using it DefOpCode defOp = new DefOpCode(new Operand[] { id, typeOp }, store); defOp.Execute(); Operand[] operands = new Operand[] { id, num }; SetOpCode setOp = new SetOpCode(operands, store); setOp.Execute(); var storedValue = Convert.ToInt32(store.Get(id)); if (storedValue != 10) { throw new Exception("Stored value != 10"); } }
internal void TestAdd() { MemoryStore store = new MemoryStore(); IdentOperand idA = new IdentOperand("A"); IdentOperand idB = new IdentOperand("B"); IdentOperand idC = new IdentOperand("C"); TypeOperand typeOp = new TypeOperand(TYPE.INT); NumOperand numA = new NumOperand(10); NumOperand numB = new NumOperand(20); // We must define the variable prior to using it DefOpCode defOp = new DefOpCode(new Operand[] { idA, typeOp }, store); defOp.Execute(); defOp = new DefOpCode(new Operand[] { idB, typeOp }, store); defOp.Execute(); defOp = new DefOpCode(new Operand[] { idC, typeOp }, store); defOp.Execute(); // Store A Operand[] operands = new Operand[] { idA, numA }; SetOpCode op = new SetOpCode(operands, store); op.Execute(); // Store B operands = new Operand[] { idB, numB }; op = new SetOpCode(operands, store); op.Execute(); // Add: C = A + B AddOpCode addOp = new AddOpCode(new Operand[] { idC, idA, idB }, store); addOp.Execute(); var storedValue = Convert.ToInt32(store.Get(idC)); if (storedValue != 30) { throw new Exception("Stored value != 30"); } }
internal void TestDef() { IdentOperand id = new IdentOperand("A"); TypeOperand typeOp = new TypeOperand(TYPE.INT); Operand[] operands = new Operand[] { id, typeOp }; MemoryStore store = new MemoryStore(); DefOpCode op = new DefOpCode(operands, store); op.Execute(); var storedValue = store.Get(id); if (storedValue != null) { throw new Exception("Stored value should have been null"); } id = new IdentOperand("@A"); operands = new Operand[] { id, typeOp }; bool noAtSignsPassed = false; try { op = new DefOpCode(operands, store); op.Execute(); } catch (Exception ex) { noAtSignsPassed = true; } if (noAtSignsPassed == false) { throw new Exception("Expected Def.Execute to fail with @ in IDENT name."); } }
private static Instruction Parse(MethodInfo methodInfo) { Instruction head = null; Instruction tail = null; var data = methodInfo.GetMethodBody().GetILAsByteArray(); var offset = 0u; while (offset < data.Length) { IOperand operand = null; short opcodeValue = data[offset++]; if (opcodeValue == 0xFE) { opcodeValue |= (short)data[offset++]; } OpCode opcode = _opcodes[opcodeValue]; switch (opcode.OperandType) { case OperandType.InlineBrTarget: { var branchTarget = Read <uint>(data, ref offset) + offset; operand = new BranchTargetOperand(branchTarget); break; } case OperandType.InlineField: { var metadataToken = Read <int>(data, ref offset); try { var fieldInfo = methodInfo.Module.ResolveField(metadataToken); operand = new FieldOperand(fieldInfo); } catch (Exception) { operand = new FieldOperand(null); } break; } case OperandType.InlineI: operand = new ImmediateOperand <uint>(opcode.OperandType, Read <uint>(data, ref offset)); break; case OperandType.InlineI8: operand = new ImmediateOperand <ulong>(opcode.OperandType, Read <ulong>(data, ref offset)); break; case OperandType.InlineMethod: { var metadataToken = Read <int>(data, ref offset); try { var inlineMethodInfo = methodInfo.Module.ResolveMethod(metadataToken); operand = new MethodOperand(inlineMethodInfo); } catch (Exception) { operand = new MethodOperand(null); } break; } case OperandType.InlineNone: break; case OperandType.InlineR: operand = new ImmediateOperand <double>(opcode.OperandType, Read <double>(data, ref offset)); break; case OperandType.InlineSig: { var metadataToken = Read <int>(data, ref offset); try { var blobData = methodInfo.Module.ResolveSignature(metadataToken); operand = new DataBlobOperand(blobData); } catch (Exception) { operand = new DataBlobOperand(null); } break; } case OperandType.InlineString: { var metadataToken = Read <int>(data, ref offset); try { var stringInfo = methodInfo.Module.ResolveString(metadataToken); operand = new StringOperand(stringInfo); } catch (Exception) { operand = new StringOperand(null); } break; } case OperandType.InlineSwitch: { var count = Read <uint>(data, ref offset); var tableOffset = offset; var switchTargets = new uint[count]; for (var i = 0; i < count; ++i) { switchTargets[i] = Read <uint>(data, ref offset) + tableOffset * count * 4; } throw new NotImplementedException(); } case OperandType.InlineTok: { var metadataToken = Read <int>(data, ref offset); try { var tokenRef = methodInfo.Module.ResolveType(metadataToken); operand = new TypeOperand(opcode.OperandType, tokenRef); } catch (Exception) { operand = new TypeOperand(opcode.OperandType, null); } break; } case OperandType.InlineType: { var metadataToken = Read <int>(data, ref offset); try { var tokenRef = methodInfo.Module.ResolveType(metadataToken, methodInfo.DeclaringType.GetGenericArguments(), methodInfo.GetGenericArguments()); operand = new TypeOperand(opcode.OperandType, tokenRef); } catch (Exception) { operand = new TypeOperand(opcode.OperandType, null); } break; } case OperandType.InlineVar: { var variableOrdinal = Read <ushort>(data, ref offset); operand = new VariableOperand(methodInfo.GetMethodBody().LocalVariables[variableOrdinal]); break; } } var instruction = new Instruction(opcode, operand); if (head == null) { head = tail = instruction; } else { tail = tail.Next = instruction; } } // Fix branch instruction targets tail = head; while (tail != null) { if (tail.Operand is BranchTargetOperand branchTargetOperand) { var next = tail.Next; while (next != null && next.Offset != branchTargetOperand.BranchTarget) { next = next.Next; } branchTargetOperand.Target = next ?? throw new InvalidProgramException("Unable to resolve branch target"); } tail = tail.Next; } return(head); }