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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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();
            }
        }
Exemple #4
0
        /// <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);
        }