Deprecate some instr info methods (use Instruction methods instead)

This commit is contained in:
wtfsck 2021-02-04 19:13:32 +01:00
parent 00c8263849
commit fe6502a05e
4 changed files with 111 additions and 50 deletions

View File

@ -126,6 +126,7 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
Assert.Equal(testCase.StackPointerIncrement, instruction.StackPointerIncrement);
var info = new InstructionInfoFactory().GetInfo(instruction);
#pragma warning disable CS0618 // Type or member is obsolete
Assert.Equal(testCase.Encoding, info.Encoding);
Assert.Equal(testCase.CpuidFeatures, info.CpuidFeatures);
Assert.Equal(testCase.RflagsRead, info.RflagsRead);
@ -137,6 +138,7 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
Assert.Equal(testCase.IsStackInstruction, info.IsStackInstruction);
Assert.Equal(testCase.IsSaveRestoreInstruction, info.IsSaveRestoreInstruction);
Assert.Equal(testCase.FlowControl, info.FlowControl);
#pragma warning restore CS0618 // Type or member is obsolete
Assert.Equal(testCase.Op0Access, info.Op0Access);
Assert.Equal(testCase.Op1Access, info.Op1Access);
Assert.Equal(testCase.Op2Access, info.Op2Access);
@ -184,11 +186,13 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
for (int i = instruction.OpCount; i < IcedConstants.MaxOpCount; i++)
Assert.Equal(OpAccess.None, info.GetOpAccess(i));
#pragma warning disable CS0618 // Type or member is obsolete
Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined));
Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined));
Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined));
Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet));
Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified);
#pragma warning restore CS0618 // Type or member is obsolete
var info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.None);
CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true);
@ -199,9 +203,10 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage);
CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false);
#pragma warning disable CS0618 // Type or member is obsolete
Assert.Equal(info.Encoding, instruction.Code.Encoding());
#if ENCODER && OPCODE_INFO
Assert.Equal(code.ToOpCode().Encoding, instruction.Code.Encoding());
Assert.Equal(code.ToOpCode().Encoding, info.Encoding);
#endif
Assert.Equal(info.CpuidFeatures, instruction.Code.CpuidFeatures());
Assert.Equal(info.FlowControl, instruction.Code.FlowControl());
@ -221,6 +226,7 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
Assert.Equal(info.RflagsSet, instruction.RflagsSet);
Assert.Equal(info.RflagsUndefined, instruction.RflagsUndefined);
Assert.Equal(info.RflagsModified, instruction.RflagsModified);
#pragma warning restore CS0618 // Type or member is obsolete
}
void CheckEqual(ref InstructionInfo info1, ref InstructionInfo info2, bool hasRegs2, bool hasMem2) {
@ -232,23 +238,27 @@ namespace Iced.UnitTests.Intel.InstructionInfoTests {
Assert.Equal(info1.GetUsedMemory(), info2.GetUsedMemory(), UsedMemoryEqualityComparer.Instance);
else
Assert.Empty(info2.GetUsedMemory());
#pragma warning disable CS0618 // Type or member is obsolete
Assert.Equal(info1.IsPrivileged, info2.IsPrivileged);
Assert.Equal(info1.IsStackInstruction, info2.IsStackInstruction);
Assert.Equal(info1.IsSaveRestoreInstruction, info2.IsSaveRestoreInstruction);
Assert.Equal(info1.Encoding, info2.Encoding);
Assert.Equal(info1.CpuidFeatures, info2.CpuidFeatures);
Assert.Equal(info1.FlowControl, info2.FlowControl);
#pragma warning restore CS0618 // Type or member is obsolete
Assert.Equal(info1.Op0Access, info2.Op0Access);
Assert.Equal(info1.Op1Access, info2.Op1Access);
Assert.Equal(info1.Op2Access, info2.Op2Access);
Assert.Equal(info1.Op3Access, info2.Op3Access);
Assert.Equal(info1.Op4Access, info2.Op4Access);
#pragma warning disable CS0618 // Type or member is obsolete
Assert.Equal(info1.RflagsRead, info2.RflagsRead);
Assert.Equal(info1.RflagsWritten, info2.RflagsWritten);
Assert.Equal(info1.RflagsCleared, info2.RflagsCleared);
Assert.Equal(info1.RflagsSet, info2.RflagsSet);
Assert.Equal(info1.RflagsUndefined, info2.RflagsUndefined);
Assert.Equal(info1.RflagsModified, info2.RflagsModified);
#pragma warning restore CS0618 // Type or member is obsolete
}
IEnumerable<UsedRegister> GetUsedRegisters(IEnumerable<UsedRegister> usedRegisterIterator) {

View File

@ -126,33 +126,45 @@ namespace Iced.Intel {
/// <summary>
/// <see langword="true"/> if it's a privileged instruction (all CPL=0 instructions (except <c>VMCALL</c>) and IOPL instructions <c>IN</c>, <c>INS</c>, <c>OUT</c>, <c>OUTS</c>, <c>CLI</c>, <c>STI</c>)
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.IsPrivileged) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly bool IsPrivileged => (flags & (uint)Flags1.Privileged) != 0;
/// <summary>
/// <see langword="true"/> if this is an instruction that implicitly uses the stack pointer (<c>SP</c>/<c>ESP</c>/<c>RSP</c>), eg. <c>CALL</c>, <c>PUSH</c>, <c>POP</c>, <c>RET</c>, etc.
/// See also <see cref="Instruction.StackPointerIncrement"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.IsStackInstruction) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly bool IsStackInstruction => (flags & (uint)Flags1.StackInstruction) != 0;
/// <summary>
/// <see langword="true"/> if it's an instruction that saves or restores too many registers (eg. <c>FXRSTOR</c>, <c>XSAVE</c>, etc).
/// <see cref="GetUsedRegisters"/> won't return all accessed registers.
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.IsSaveRestoreInstruction) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly bool IsSaveRestoreInstruction => (flags & (uint)Flags1.SaveRestore) != 0;
/// <summary>
/// Instruction encoding, eg. Legacy, 3DNow!, VEX, EVEX, XOP
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.Encoding) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly EncodingKind Encoding => (EncodingKind)encoding;
/// <summary>
/// Gets the CPU or CPUID feature flags
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.CpuidFeatures) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly CpuidFeature[] CpuidFeatures => CpuidFeatureInternalData.ToCpuidFeatures[cpuidFeatureInternal];
/// <summary>
/// Control flow info
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.FlowControl) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly FlowControl FlowControl => (FlowControl)flowControl;
/// <summary>
@ -231,31 +243,43 @@ namespace Iced.Intel {
/// <summary>
/// All flags that are read by the CPU when executing the instruction. See also <see cref="RflagsModified"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsRead) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsRead => (RflagsBits)RflagsInfoConstants.flagsRead[rflagsInfo];
/// <summary>
/// All flags that are written by the CPU, except those flags that are known to be undefined, always set or always cleared. See also <see cref="RflagsModified"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsWritten) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsWritten => (RflagsBits)RflagsInfoConstants.flagsWritten[rflagsInfo];
/// <summary>
/// All flags that are always cleared by the CPU. See also <see cref="RflagsModified"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsCleared) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsCleared => (RflagsBits)RflagsInfoConstants.flagsCleared[rflagsInfo];
/// <summary>
/// All flags that are always set by the CPU. See also <see cref="RflagsModified"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsSet) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsSet => (RflagsBits)RflagsInfoConstants.flagsSet[rflagsInfo];
/// <summary>
/// All flags that are undefined after executing the instruction. See also <see cref="RflagsModified"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsUndefined) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsUndefined => (RflagsBits)RflagsInfoConstants.flagsUndefined[rflagsInfo];
/// <summary>
/// All flags that are modified by the CPU. This is <see cref="RflagsWritten"/> + <see cref="RflagsCleared"/> + <see cref="RflagsSet"/> + <see cref="RflagsUndefined"/>
/// </summary>
[System.Obsolete("Use " + nameof(Instruction) + "." + nameof(Instruction.RflagsModified) + " instead", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public readonly RflagsBits RflagsModified => (RflagsBits)RflagsInfoConstants.flagsModified[rflagsInfo];
}
}

View File

@ -378,6 +378,7 @@ impl InstructionInfo {
/// `true` if it's a privileged instruction (all CPL=0 instructions (except `VMCALL`) and IOPL instructions `IN`, `INS`, `OUT`, `OUTS`, `CLI`, `STI`)
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::is_privileged() instead")]
pub fn is_privileged(&self) -> bool {
(self.flags & IIFlags::PRIVILEGED) != 0
}
@ -388,6 +389,7 @@ impl InstructionInfo {
/// [`Instruction::stack_pointer_increment()`]: struct.Instruction.html#method.stack_pointer_increment
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::is_stack_instruction() instead")]
pub fn is_stack_instruction(&self) -> bool {
(self.flags & IIFlags::STACK_INSTRUCTION) != 0
}
@ -398,6 +400,7 @@ impl InstructionInfo {
/// [`used_registers()`]: #method.used_registers
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::is_save_restore_instruction() instead")]
pub fn is_save_restore_instruction(&self) -> bool {
(self.flags & IIFlags::SAVE_RESTORE) != 0
}
@ -405,6 +408,7 @@ impl InstructionInfo {
/// Instruction encoding, eg. Legacy, 3DNow!, VEX, EVEX, XOP
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::encoding() instead")]
pub fn encoding(&self) -> EncodingKind {
self.encoding
}
@ -412,6 +416,7 @@ impl InstructionInfo {
/// Gets the CPU or CPUID feature flags
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::cpuid_features() instead")]
pub fn cpuid_features(&self) -> &'static [CpuidFeature] {
unsafe { *self::cpuid_table::CPUID.get_unchecked(self.cpuid_feature_internal) }
}
@ -419,6 +424,7 @@ impl InstructionInfo {
/// Control flow info
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::flow_control() instead")]
pub fn flow_control(&self) -> FlowControl {
self.flow_control
}
@ -496,6 +502,7 @@ impl InstructionInfo {
/// [`rflags_modified()`]: #method.rflags_modified
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_read() instead")]
pub fn rflags_read(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_READ.get_unchecked(self.rflags_info) as u32 }
}
@ -507,6 +514,7 @@ impl InstructionInfo {
/// [`rflags_modified()`]: #method.rflags_modified
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_written() instead")]
pub fn rflags_written(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_WRITTEN.get_unchecked(self.rflags_info) as u32 }
}
@ -518,6 +526,7 @@ impl InstructionInfo {
/// [`rflags_modified()`]: #method.rflags_modified
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_cleared() instead")]
pub fn rflags_cleared(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_CLEARED.get_unchecked(self.rflags_info) as u32 }
}
@ -529,6 +538,7 @@ impl InstructionInfo {
/// [`rflags_modified()`]: #method.rflags_modified
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_set() instead")]
pub fn rflags_set(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_SET.get_unchecked(self.rflags_info) as u32 }
}
@ -540,6 +550,7 @@ impl InstructionInfo {
/// [`rflags_modified()`]: #method.rflags_modified
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_undefined() instead")]
pub fn rflags_undefined(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_UNDEFINED.get_unchecked(self.rflags_info) as u32 }
}
@ -549,6 +560,7 @@ impl InstructionInfo {
/// [`RflagsBits`]: struct.RflagsBits.html
#[must_use]
#[inline]
#[deprecated(since = "1.11.0", note = "Use Instruction::rflags_modified() instead")]
pub fn rflags_modified(&self) -> u32 {
unsafe { *super::info::rflags_table::FLAGS_MODIFIED.get_unchecked(self.rflags_info) as u32 }
}

View File

@ -151,6 +151,8 @@ fn test_info_core(tc: &InstrInfoTestCase, factory: &mut InstructionInfoFactory)
let mut factory1 = InstructionInfoFactory::new();
let info = factory1.info(&instr);
#[allow(deprecated)]
{
assert_eq!(info.encoding(), tc.encoding);
assert_eq!(info.cpuid_features(), tc.cpuid_features.as_slice());
assert_eq!(info.rflags_read(), tc.rflags_read);
@ -162,6 +164,7 @@ fn test_info_core(tc: &InstrInfoTestCase, factory: &mut InstructionInfoFactory)
assert_eq!(info.is_stack_instruction(), tc.is_stack_instruction);
assert_eq!(info.is_save_restore_instruction(), tc.is_save_restore_instruction);
assert_eq!(info.flow_control(), tc.flow_control);
}
assert_eq!(info.op0_access(), tc.op0_access);
assert_eq!(info.op1_access(), tc.op1_access);
assert_eq!(info.op2_access(), tc.op2_access);
@ -208,11 +211,14 @@ fn test_info_core(tc: &InstrInfoTestCase, factory: &mut InstructionInfoFactory)
}
assert!(info.try_op_access(IcedConstants::MAX_OP_COUNT as u32).is_err());
#[allow(deprecated)]
{
assert_eq!(info.rflags_written() & (info.rflags_cleared() | info.rflags_set() | info.rflags_undefined()), RflagsBits::NONE);
assert_eq!(info.rflags_cleared() & (info.rflags_written() | info.rflags_set() | info.rflags_undefined()), RflagsBits::NONE);
assert_eq!(info.rflags_set() & (info.rflags_written() | info.rflags_cleared() | info.rflags_undefined()), RflagsBits::NONE);
assert_eq!(info.rflags_undefined() & (info.rflags_written() | info.rflags_cleared() | info.rflags_set()), RflagsBits::NONE);
assert_eq!(info.rflags_modified(), info.rflags_written() | info.rflags_cleared() | info.rflags_set() | info.rflags_undefined());
}
let mut factory2 = InstructionInfoFactory::new();
let info2 = factory2.info_options(&instr, InstructionInfoOptions::NONE);
@ -248,10 +254,12 @@ fn test_info_core(tc: &InstrInfoTestCase, factory: &mut InstructionInfoFactory)
check_equal(info, info2, false, false);
}
#[allow(deprecated)]
{
assert_eq!(instr.code().encoding(), info.encoding());
#[cfg(feature = "encoder")]
{
assert_eq!(instr.code().encoding(), tc.code.op_code().encoding());
assert_eq!(info.encoding(), tc.code.op_code().encoding());
}
assert_eq!(instr.code().cpuid_features(), info.cpuid_features());
assert_eq!(instr.code().flow_control(), info.flow_control());
@ -271,6 +279,7 @@ fn test_info_core(tc: &InstrInfoTestCase, factory: &mut InstructionInfoFactory)
assert_eq!(instr.rflags_set(), info.rflags_set());
assert_eq!(instr.rflags_undefined(), info.rflags_undefined());
assert_eq!(instr.rflags_modified(), info.rflags_modified());
}
}
fn check_equal(info1: &InstructionInfo, info2: &InstructionInfo, has_regs2: bool, has_mem2: bool) {
@ -284,23 +293,29 @@ fn check_equal(info1: &InstructionInfo, info2: &InstructionInfo, has_regs2: bool
} else {
assert!(info2.used_memory().is_empty());
}
#[allow(deprecated)]
{
assert_eq!(info2.is_privileged(), info1.is_privileged());
assert_eq!(info2.is_stack_instruction(), info1.is_stack_instruction());
assert_eq!(info2.is_save_restore_instruction(), info1.is_save_restore_instruction());
assert_eq!(info2.encoding(), info1.encoding());
assert_eq!(info2.cpuid_features(), info1.cpuid_features());
assert_eq!(info2.flow_control(), info1.flow_control());
}
assert_eq!(info2.op0_access(), info1.op0_access());
assert_eq!(info2.op1_access(), info1.op1_access());
assert_eq!(info2.op2_access(), info1.op2_access());
assert_eq!(info2.op3_access(), info1.op3_access());
assert_eq!(info2.op4_access(), info1.op4_access());
#[allow(deprecated)]
{
assert_eq!(info2.rflags_read(), info1.rflags_read());
assert_eq!(info2.rflags_written(), info1.rflags_written());
assert_eq!(info2.rflags_cleared(), info1.rflags_cleared());
assert_eq!(info2.rflags_set(), info1.rflags_set());
assert_eq!(info2.rflags_undefined(), info1.rflags_undefined());
assert_eq!(info2.rflags_modified(), info1.rflags_modified());
}
}
#[must_use]