private object ResolveOperand(ByteCodeInstructionCollection allInstructions, ByteCodeInstruction instruction) { switch (instruction.OpCode.OperandType) { case ByteCodeOperandType.PrimitiveType: return((PrimitiveType)(byte)instruction.Operand); case ByteCodeOperandType.ConstantIndex: case ByteCodeOperandType.WideConstantIndex: return(OperandResolver?.ResolveConstant(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.FieldIndex: return(OperandResolver?.ResolveField(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.MethodIndex: return(OperandResolver?.ResolveMethod(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.ClassIndex: return(OperandResolver?.ResolveClass(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.BranchOffset: case ByteCodeOperandType.WideBranchOffset: int offset = Convert.ToInt32(instruction.Operand); return(allInstructions.GetByOffset(instruction.Offset + offset) ?? instruction.Operand); } return(instruction.Operand); }
private object ResolveOperand(ByteCodeInstructionCollection allInstructions, ByteCodeInstruction instruction) { switch (instruction.OpCode.OperandType) { case ByteCodeOperandType.PrimitiveType: return((PrimitiveType)(byte)instruction.Operand); case ByteCodeOperandType.ConstantIndex: case ByteCodeOperandType.WideConstantIndex: return(OperandResolver?.ResolveConstant(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.FieldIndex: return(OperandResolver?.ResolveField(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.MethodIndex: return(OperandResolver?.ResolveMethod(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.ClassIndex: return(OperandResolver?.ResolveClass(Convert.ToInt32(instruction.Operand)) ?? instruction.Operand); case ByteCodeOperandType.DynamicIndex: return(OperandResolver?.ResolveDynamic(Convert.ToInt32(instruction.Operand) >> 16) ?? instruction.Operand); case ByteCodeOperandType.BranchOffset: case ByteCodeOperandType.WideBranchOffset: int offset = Convert.ToInt32(instruction.Operand); return(allInstructions.GetByOffset(instruction.Offset + offset) ?? instruction.Operand); case ByteCodeOperandType.TableSwitch: var table = (TableSwitch)instruction.Operand; table.DefaultOffset += instruction.Offset; for (int i = 0; i < table.Offsets.Count; i++) { table.Offsets[i] += instruction.Offset; } return(table); case ByteCodeOperandType.LookupSwitch: var lookup = (LookupSwitch)instruction.Operand; lookup.DefaultOffset += instruction.Offset; foreach (int key in lookup.Table.Keys) { lookup.Table[key] += instruction.Offset; } return(lookup); } return(instruction.Operand); }
private void WriteOperand(ByteCodeInstruction instruction) { switch (instruction.OpCode.OperandType) { case ByteCodeOperandType.None: break; case ByteCodeOperandType.Byte: case ByteCodeOperandType.LocalIndex: case ByteCodeOperandType.PrimitiveType: _writer.Write(Convert.ToByte(instruction.Operand)); break; case ByteCodeOperandType.Short: case ByteCodeOperandType.LocalConst: _writer.Write(Convert.ToInt16(instruction.Operand)); break; case ByteCodeOperandType.FieldIndex: _writer.Write(instruction.Operand is FieldReference fieldRef ? (ushort)OperandBuilder.GetFieldIndex(fieldRef) : Convert.ToUInt16(instruction.Operand)); break; case ByteCodeOperandType.MethodIndex: _writer.Write(instruction.Operand is MethodReference methodRef ? (ushort)OperandBuilder.GetMethodIndex(methodRef) : Convert.ToUInt16(instruction.Operand)); break; case ByteCodeOperandType.ClassIndex: _writer.Write(instruction.Operand is ClassReference classRef ? (ushort)OperandBuilder.GetClassIndex(classRef) : Convert.ToUInt16(instruction.Operand)); break; case ByteCodeOperandType.ConstantIndex: _writer.Write((byte)OperandBuilder.GetLiteralIndex(instruction.Operand)); break; case ByteCodeOperandType.WideConstantIndex: _writer.Write((ushort)OperandBuilder.GetLiteralIndex(instruction.Operand)); break; case ByteCodeOperandType.BranchOffset: { short relativeOffset; if (instruction.Operand is ByteCodeInstruction target) { relativeOffset = (short)(target.Offset - instruction.Offset); } else { relativeOffset = Convert.ToInt16(instruction.Operand); } _writer.Write(relativeOffset); break; } case ByteCodeOperandType.WideBranchOffset: { int relativeOffset; if (instruction.Operand is ByteCodeInstruction target) { relativeOffset = (target.Offset - instruction.Offset); } else { relativeOffset = Convert.ToInt32(instruction.Operand); } _writer.Write(relativeOffset); break; } case ByteCodeOperandType.TableSwitch: case ByteCodeOperandType.LookupSwitch: _writer.Position = FileSegment.Align((uint)_writer.Position, 4); ((ISwitchOperand)instruction.Operand).Write(_writer, instruction.Offset); break; case ByteCodeOperandType.WideIndexCountZero: case ByteCodeOperandType.WideIndexByte: _writer.Write(Convert.ToInt32(instruction.Operand)); break; case ByteCodeOperandType.DynamicIndex: _writer.Write(instruction.Operand is DynamicInvocation invocation ? OperandBuilder.GetDynamicIndex(invocation) << 16 : Convert.ToInt32(instruction.Operand)); break; default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Writes a single instruction to the output stream. /// </summary> /// <param name="instruction">The instruction to write.</param> /// <remarks> /// Some instructions have different byte layouts depending on the offsets they are located at. /// Make sure the offsets have been calculated before passing on the instructions to the assembler. /// </remarks> public void Write(ByteCodeInstruction instruction) { _writer.Write((byte)instruction.OpCode.Code); WriteOperand(instruction); }