diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 0861cf311..55df8d213 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -18,7 +18,12 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. -#include +#include +#include +#include + +#include "sharedilinstruction.h" + #ifdef BINARYNINJACORE_LIBRARY #include "highlevelilfunction.h" #include "highlevelilssafunction.h" @@ -36,203 +41,230 @@ using namespace BinaryNinja; using namespace std; #endif +namespace { + +struct OperandUsageType +{ + HighLevelILOperandUsage usage; + HighLevelILOperandType type; -unordered_map HighLevelILInstructionBase::operandTypeForUsage = { - {SourceExprHighLevelOperandUsage, ExprHighLevelOperand}, - {VariableHighLevelOperandUsage, VariableHighLevelOperand}, - {DestVariableHighLevelOperandUsage, VariableHighLevelOperand}, - {SSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, - {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, - {DestExprHighLevelOperandUsage, ExprHighLevelOperand}, - {LeftExprHighLevelOperandUsage, ExprHighLevelOperand}, - {RightExprHighLevelOperandUsage, ExprHighLevelOperand}, - {CarryExprHighLevelOperandUsage, ExprHighLevelOperand}, - {IndexExprHighLevelOperandUsage, ExprHighLevelOperand}, - {ConditionExprHighLevelOperandUsage, ExprHighLevelOperand}, - {ConditionPhiExprHighLevelOperandUsage, ExprHighLevelOperand}, - {TrueExprHighLevelOperandUsage, ExprHighLevelOperand}, - {FalseExprHighLevelOperandUsage, ExprHighLevelOperand}, - {LoopExprHighLevelOperandUsage, ExprHighLevelOperand}, - {InitExprHighLevelOperandUsage, ExprHighLevelOperand}, - {UpdateExprHighLevelOperandUsage, ExprHighLevelOperand}, - {DefaultExprHighLevelOperandUsage, ExprHighLevelOperand}, - {HighExprHighLevelOperandUsage, ExprHighLevelOperand}, - {LowExprHighLevelOperandUsage, ExprHighLevelOperand}, - {OffsetHighLevelOperandUsage, IntegerHighLevelOperand}, - {MemberIndexHighLevelOperandUsage, IndexHighLevelOperand}, - {ConstantHighLevelOperandUsage, IntegerHighLevelOperand}, - {ConstantDataHighLevelOperandUsage, ConstantDataHighLevelOperand}, - {VectorHighLevelOperandUsage, IntegerHighLevelOperand}, - {IntrinsicHighLevelOperandUsage, IntrinsicHighLevelOperand}, - {TargetHighLevelOperandUsage, IndexHighLevelOperand}, - {ParameterExprsHighLevelOperandUsage, ExprListHighLevelOperand}, - {SourceExprsHighLevelOperandUsage, ExprListHighLevelOperand}, - {DestExprsHighLevelOperandUsage, ExprListHighLevelOperand}, - {BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand}, - {CasesHighLevelOperandUsage, ExprListHighLevelOperand}, - {ValueExprsHighLevelOperandUsage, ExprListHighLevelOperand}, - {SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand}, - {SourceMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}, - {SourceMemoryVersionsHighLevelOperandUsage, IndexListHighLevelOperand}, - {DestMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}}; - - -unordered_map> - HighLevelILInstructionBase::operationOperandUsage = {{HLIL_NOP, {}}, {HLIL_BREAK, {}}, {HLIL_CONTINUE, {}}, - {HLIL_NORET, {}}, {HLIL_BP, {}}, {HLIL_UNDEF, {}}, {HLIL_UNIMPL, {}}, {HLIL_UNREACHABLE, {}}, - {HLIL_BLOCK, {BlockExprsHighLevelOperandUsage}}, - {HLIL_IF, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage, FalseExprHighLevelOperandUsage}}, - {HLIL_WHILE, {ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, - {HLIL_WHILE_SSA, - {ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, - {HLIL_DO_WHILE, {LoopExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}}, - {HLIL_DO_WHILE_SSA, - {LoopExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}}, - {HLIL_FOR, {InitExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, UpdateExprHighLevelOperandUsage, - LoopExprHighLevelOperandUsage}}, - {HLIL_FOR_SSA, - {InitExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, - UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, - {HLIL_SWITCH, - {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage, CasesHighLevelOperandUsage}}, - {HLIL_CASE, {ValueExprsHighLevelOperandUsage, TrueExprHighLevelOperandUsage}}, - {HLIL_JUMP, {DestExprHighLevelOperandUsage}}, {HLIL_RET, {SourceExprsHighLevelOperandUsage}}, - {HLIL_GOTO, {TargetHighLevelOperandUsage}}, {HLIL_LABEL, {TargetHighLevelOperandUsage}}, - {HLIL_VAR_DECLARE, {VariableHighLevelOperandUsage}}, - {HLIL_VAR_INIT, {DestVariableHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, - {HLIL_VAR_INIT_SSA, {DestSSAVariableHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, - {HLIL_ASSIGN, {DestExprHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, - {HLIL_ASSIGN_UNPACK, {DestExprsHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, - {HLIL_ASSIGN_MEM_SSA, {DestExprHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, - SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_ASSIGN_UNPACK_MEM_SSA, {DestExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, - SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_VAR, {VariableHighLevelOperandUsage}}, {HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}}, - {HLIL_VAR_PHI, {DestSSAVariableHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage}}, - {HLIL_MEM_PHI, {DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionsHighLevelOperandUsage}}, - {HLIL_STRUCT_FIELD, - {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, - {HLIL_ARRAY_INDEX, {SourceExprHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, - {HLIL_ARRAY_INDEX_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, - IndexExprHighLevelOperandUsage}}, - {HLIL_SPLIT, {HighExprHighLevelOperandUsage, LowExprHighLevelOperandUsage}}, - {HLIL_DEREF, {SourceExprHighLevelOperandUsage}}, - {HLIL_DEREF_FIELD, - {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, - {HLIL_DEREF_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_DEREF_FIELD_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, - OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, - {HLIL_ADDRESS_OF, {SourceExprHighLevelOperandUsage}}, - {HLIL_CALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, - {HLIL_SYSCALL, {ParameterExprsHighLevelOperandUsage}}, - {HLIL_TAILCALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, - {HLIL_INTRINSIC, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, - {HLIL_CALL_SSA, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage, - DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_SYSCALL_SSA, {ParameterExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, - SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_INTRINSIC_SSA, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage, - DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, - {HLIL_TRAP, {VectorHighLevelOperandUsage}}, - {HLIL_CONST, {ConstantHighLevelOperandUsage}}, - {HLIL_CONST_PTR, {ConstantHighLevelOperandUsage}}, - {HLIL_EXTERN_PTR, {ConstantHighLevelOperandUsage, OffsetHighLevelOperandUsage}}, - {HLIL_FLOAT_CONST, {ConstantHighLevelOperandUsage}}, {HLIL_IMPORT, {ConstantHighLevelOperandUsage}}, - {HLIL_CONST_DATA, {ConstantDataHighLevelOperandUsage}}, - {HLIL_ADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_SUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_AND, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_OR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_XOR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_LSL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_LSR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_ASR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_ROL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_ROR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MULU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MULS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_DIVU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_DIVS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MODU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MODS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_SLT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_ULT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_SLE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_ULE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_SGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_UGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_SGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_CMP_UGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_TEST_BIT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_ADD_OVERFLOW, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_ADC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, - {HLIL_SBB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, - {HLIL_RLC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, - {HLIL_RRC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, - {HLIL_DIVU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_DIVS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MODU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_MODS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_NEG, {SourceExprHighLevelOperandUsage}}, {HLIL_NOT, {SourceExprHighLevelOperandUsage}}, - {HLIL_SX, {SourceExprHighLevelOperandUsage}}, {HLIL_ZX, {SourceExprHighLevelOperandUsage}}, - {HLIL_LOW_PART, {SourceExprHighLevelOperandUsage}}, {HLIL_BOOL_TO_INT, {SourceExprHighLevelOperandUsage}}, - {HLIL_UNIMPL_MEM, {SourceExprHighLevelOperandUsage}}, - {HLIL_FADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FSUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FMUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FDIV, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FSQRT, {SourceExprHighLevelOperandUsage}}, {HLIL_FNEG, {SourceExprHighLevelOperandUsage}}, - {HLIL_FABS, {SourceExprHighLevelOperandUsage}}, {HLIL_FLOAT_TO_INT, {SourceExprHighLevelOperandUsage}}, - {HLIL_INT_TO_FLOAT, {SourceExprHighLevelOperandUsage}}, {HLIL_FLOAT_CONV, {SourceExprHighLevelOperandUsage}}, - {HLIL_ROUND_TO_INT, {SourceExprHighLevelOperandUsage}}, {HLIL_FLOOR, {SourceExprHighLevelOperandUsage}}, - {HLIL_CEIL, {SourceExprHighLevelOperandUsage}}, {HLIL_FTRUNC, {SourceExprHighLevelOperandUsage}}, - {HLIL_FCMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_LT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_LE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_GE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_GT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_O, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, - {HLIL_FCMP_UO, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}}; - - -static unordered_map> - GetOperandIndexForOperandUsages() -{ - unordered_map> result; - result.reserve(HighLevelILInstructionBase::operationOperandUsage.size()); - for (auto& operation : HighLevelILInstructionBase::operationOperandUsage) + constexpr auto operator<=>(const OperandUsageType& other) const { - result[operation.first] = unordered_map(); - result[operation.first].reserve(operation.second.size()); - size_t operand = 0; - for (auto usage : operation.second) - { - result[operation.first][usage] = operand; - switch (HighLevelILInstructionBase::operandTypeForUsage[usage]) - { - case SSAVariableHighLevelOperand: - case SSAVariableListHighLevelOperand: - case ExprListHighLevelOperand: - case IndexListHighLevelOperand: - // SSA variables and lists take two operand slots - operand += 2; - break; - default: - operand++; - break; - } - } + return usage <=> other.usage; } - return result; +}; + +static constexpr std::array s_operandTypeForUsage = { + OperandUsageType{SourceExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{VariableHighLevelOperandUsage, VariableHighLevelOperand}, + OperandUsageType{DestVariableHighLevelOperandUsage, VariableHighLevelOperand}, + OperandUsageType{SSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, + OperandUsageType{DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, + OperandUsageType{DestExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{LeftExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{RightExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{CarryExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{IndexExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{ConditionExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{ConditionPhiExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{TrueExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{FalseExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{LoopExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{InitExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{UpdateExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{DefaultExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{HighExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{LowExprHighLevelOperandUsage, ExprHighLevelOperand}, + OperandUsageType{OffsetHighLevelOperandUsage, IntegerHighLevelOperand}, + OperandUsageType{MemberIndexHighLevelOperandUsage, IndexHighLevelOperand}, + OperandUsageType{ConstantHighLevelOperandUsage, IntegerHighLevelOperand}, + OperandUsageType{ConstantDataHighLevelOperandUsage, ConstantDataHighLevelOperand}, + OperandUsageType{VectorHighLevelOperandUsage, IntegerHighLevelOperand}, + OperandUsageType{IntrinsicHighLevelOperandUsage, IntrinsicHighLevelOperand}, + OperandUsageType{TargetHighLevelOperandUsage, IndexHighLevelOperand}, + OperandUsageType{ParameterExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{SourceExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{DestExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{CasesHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{ValueExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + OperandUsageType{SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand}, + OperandUsageType{SourceMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}, + OperandUsageType{SourceMemoryVersionsHighLevelOperandUsage, IndexListHighLevelOperand}, + OperandUsageType{DestMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand} +}; + +static_assert(std::is_sorted(s_operandTypeForUsage.begin(), s_operandTypeForUsage.end()), + "Operand type mapping array is not sorted by usage value"); + +constexpr inline HighLevelILOperandType OperandTypeForUsage(HighLevelILOperandUsage usage) +{ + if (static_cast(usage) < s_operandTypeForUsage.size()) + return s_operandTypeForUsage[usage].type; + + throw HighLevelILInstructionAccessException(); } +struct HighLevelILOperationTraits +{ + using ILOperation = BNHighLevelILOperation; + using OperandUsage = HighLevelILOperandUsage; + static constexpr size_t MaxOperands = 5; -unordered_map> - HighLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t /* operandIndex */) + { + switch (OperandTypeForUsage(usage)) + { + case SSAVariableHighLevelOperand: + case SSAVariableListHighLevelOperand: + case ExprListHighLevelOperand: + case IndexListHighLevelOperand: + return 2; + default: + return 1; + } + } +}; + +using OperandUsage = detail::ILInstructionOperandUsage; +static_assert(sizeof(OperandUsage) == 12); + + +static constexpr std::array s_instructionOperandUsage = { + OperandUsage{HLIL_NOP}, + OperandUsage{HLIL_BLOCK, {BlockExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_IF, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage, FalseExprHighLevelOperandUsage}}, + OperandUsage{HLIL_WHILE, {ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DO_WHILE, {LoopExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FOR, {InitExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SWITCH, {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage, CasesHighLevelOperandUsage}}, + OperandUsage{HLIL_CASE, {ValueExprsHighLevelOperandUsage, TrueExprHighLevelOperandUsage}}, + OperandUsage{HLIL_BREAK}, + OperandUsage{HLIL_CONTINUE}, + OperandUsage{HLIL_JUMP, {DestExprHighLevelOperandUsage}}, + OperandUsage{HLIL_RET, {SourceExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_NORET}, + OperandUsage{HLIL_GOTO, {TargetHighLevelOperandUsage}}, + OperandUsage{HLIL_LABEL, {TargetHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR_DECLARE, {VariableHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR_INIT, {DestVariableHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSIGN, {DestExprHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSIGN_UNPACK, {DestExprsHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FORCE_VER, {DestVariableHighLevelOperandUsage, VariableHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSERT, {VariableHighLevelOperandUsage, ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR, {VariableHighLevelOperandUsage}}, + OperandUsage{HLIL_STRUCT_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, + OperandUsage{HLIL_ARRAY_INDEX, {SourceExprHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SPLIT, {HighExprHighLevelOperandUsage, LowExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DEREF, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DEREF_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, + OperandUsage{HLIL_ADDRESS_OF, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CONST, {ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_CONST_DATA, {ConstantDataHighLevelOperandUsage}}, + OperandUsage{HLIL_CONST_PTR, {ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_EXTERN_PTR, {ConstantHighLevelOperandUsage, OffsetHighLevelOperandUsage}}, + OperandUsage{HLIL_FLOAT_CONST, {ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_IMPORT, {ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_ADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ADC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SBB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, + OperandUsage{HLIL_AND, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_OR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_XOR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_LSL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_LSR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ASR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ROL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_RLC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ROR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_RRC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, CarryExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MULU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MULS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DIVU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DIVU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DIVS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DIVS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MODU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MODU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MODS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_MODS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_NEG, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_NOT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SX, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ZX, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_LOW_PART, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_SLT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_ULT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_SLE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_ULE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_SGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_UGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_SGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CMP_UGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_TEST_BIT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_BOOL_TO_INT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ADD_OVERFLOW, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_SYSCALL, {ParameterExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_TAILCALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_INTRINSIC, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + OperandUsage{HLIL_BP}, + OperandUsage{HLIL_TRAP, {VectorHighLevelOperandUsage}}, + OperandUsage{HLIL_UNDEF}, + OperandUsage{HLIL_UNIMPL}, + OperandUsage{HLIL_UNIMPL_MEM, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FSUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FMUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FDIV, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FSQRT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FNEG, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FABS, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FLOAT_TO_INT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_INT_TO_FLOAT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FLOAT_CONV, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ROUND_TO_INT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FLOOR, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CEIL, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FTRUNC, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_LT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_LE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_GE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_GT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_O, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FCMP_UO, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + OperandUsage{HLIL_UNREACHABLE}, + // SSA operations + OperandUsage{HLIL_WHILE_SSA, {ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DO_WHILE_SSA, {LoopExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}}, + OperandUsage{HLIL_FOR_SSA, {InitExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR_INIT_SSA, {DestSSAVariableHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSIGN_MEM_SSA, {DestExprHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSIGN_UNPACK_MEM_SSA, {DestExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_FORCE_VER_SSA, {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSERT_SSA, {SSAVariableHighLevelOperandUsage, ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}}, + OperandUsage{HLIL_ARRAY_INDEX_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, + OperandUsage{HLIL_DEREF_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_DEREF_FIELD_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, + OperandUsage{HLIL_CALL_SSA, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_SYSCALL_SSA, {ParameterExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_INTRINSIC_SSA, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, + OperandUsage{HLIL_VAR_PHI, {DestSSAVariableHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage}}, + OperandUsage{HLIL_MEM_PHI, {DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionsHighLevelOperandUsage}}, +}; + + +VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage); + + +} // unnamed namespace bool HighLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const @@ -510,13 +542,11 @@ HighLevelILSSAVariableList::operator vector() const HighLevelILOperand::HighLevelILOperand( const HighLevelILInstruction& instr, HighLevelILOperandUsage usage, size_t operandIndex) : - m_instr(instr), - m_usage(usage), m_operandIndex(operandIndex) + m_instr(instr), + m_usage(usage), + m_type(OperandTypeForUsage(m_usage)), + m_operandIndex(operandIndex) { - auto i = HighLevelILInstructionBase::operandTypeForUsage.find(m_usage); - if (i == HighLevelILInstructionBase::operandTypeForUsage.end()) - throw HighLevelILInstructionAccessException(); - m_type = i->second; } @@ -602,19 +632,19 @@ HighLevelILIndexList HighLevelILOperand::GetIndexList() const const HighLevelILOperand HighLevelILOperandList::ListIterator::operator*() { - HighLevelILOperandUsage usage = *pos; - auto i = owner->m_operandIndexMap.find(usage); - if (i == owner->m_operandIndexMap.end()) + if (index >= owner->m_count) throw HighLevelILInstructionAccessException(); - return HighLevelILOperand(owner->m_instr, usage, i->second); + HighLevelILOperandUsage usage = owner->m_usages[index]; + return HighLevelILOperand(owner->m_instr, usage, owner->m_indices[index]); } HighLevelILOperandList::HighLevelILOperandList(const HighLevelILInstruction& instr, - const vector& usageList, - const unordered_map& operandIndexMap) : + const HighLevelILOperandUsage* usages, + const uint8_t* indices, + uint8_t count) : m_instr(instr), - m_usageList(usageList), m_operandIndexMap(operandIndexMap) + m_usages(usages), m_indices(indices), m_count(count) {} @@ -622,7 +652,7 @@ HighLevelILOperandList::const_iterator HighLevelILOperandList::begin() const { const_iterator result; result.owner = this; - result.pos = m_usageList.begin(); + result.index = 0; return result; } @@ -631,24 +661,23 @@ HighLevelILOperandList::const_iterator HighLevelILOperandList::end() const { const_iterator result; result.owner = this; - result.pos = m_usageList.end(); + result.index = m_count; return result; } size_t HighLevelILOperandList::size() const { - return m_usageList.size(); + return m_count; } const HighLevelILOperand HighLevelILOperandList::operator[](size_t i) const { - HighLevelILOperandUsage usage = m_usageList[i]; - auto indexMap = m_operandIndexMap.find(usage); - if (indexMap == m_operandIndexMap.end()) + if (i >= m_count) throw HighLevelILInstructionAccessException(); - return HighLevelILOperand(m_instr, usage, indexMap->second); + HighLevelILOperandUsage usage = m_usages[i]; + return HighLevelILOperand(m_instr, usage, m_indices[i]); } @@ -718,13 +747,11 @@ HighLevelILInstruction::HighLevelILInstruction(const HighLevelILInstructionBase& HighLevelILOperandList HighLevelILInstructionBase::GetOperands() const { - auto usage = operationOperandUsage.find(operation); - if (usage == operationOperandUsage.end()) - throw HighLevelILInstructionAccessException(); - auto operandIndex = operationOperandIndex.find(operation); - if (operandIndex == operationOperandIndex.end()) + if (operation >= s_instructionOperandUsage.size()) throw HighLevelILInstructionAccessException(); - return HighLevelILOperandList(*(const HighLevelILInstruction*)this, usage->second, operandIndex->second); + + const auto& info = s_instructionOperandUsage[operation]; + return HighLevelILOperandList(*(const HighLevelILInstruction*)this, info.usages, info.indices, info.count); } @@ -2176,14 +2203,20 @@ bool HighLevelILInstruction::operator!=(const HighLevelILInstruction& other) con bool HighLevelILInstruction::GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const { - auto operationIter = HighLevelILInstructionBase::operationOperandIndex.find(operation); - if (operationIter == HighLevelILInstructionBase::operationOperandIndex.end()) - return false; - auto usageIter = operationIter->second.find(usage); - if (usageIter == operationIter->second.end()) + if (operation >= s_instructionOperandUsage.size()) return false; - operandIndex = usageIter->second; - return true; + + const auto& info = s_instructionOperandUsage[operation]; + for (uint8_t i = 0; i < info.count; ++i) + { + if (info.usages[i] == usage) + { + operandIndex = info.indices[i]; + return true; + } + } + + return false; } diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index 53a3c5677..84afeb98e 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -62,7 +62,7 @@ namespace BinaryNinja /*! \ingroup highlevelil */ - enum HighLevelILOperandType + enum HighLevelILOperandType : uint8_t { IntegerHighLevelOperand, ConstantDataHighLevelOperand, @@ -79,7 +79,7 @@ namespace BinaryNinja /*! \ingroup highlevelil */ - enum HighLevelILOperandUsage + enum HighLevelILOperandUsage : uint8_t { SourceExprHighLevelOperandUsage, VariableHighLevelOperandUsage, @@ -358,10 +358,6 @@ namespace BinaryNinja size_t exprIndex, instructionIndex; bool ast; - static _STD_UNORDERED_MAP operandTypeForUsage; - static _STD_UNORDERED_MAP> operationOperandUsage; - static _STD_UNORDERED_MAP> - operationOperandIndex; HighLevelILOperandList GetOperands() const; @@ -856,28 +852,29 @@ namespace BinaryNinja typedef value_type reference; const HighLevelILOperandList* owner; - _STD_VECTOR::const_iterator pos; - bool operator==(const ListIterator& a) const { return pos == a.pos; } - bool operator!=(const ListIterator& a) const { return pos != a.pos; } - bool operator<(const ListIterator& a) const { return pos < a.pos; } + size_t index; + constexpr bool operator==(const ListIterator& a) const { return index == a.index; } + constexpr auto operator<=>(const ListIterator& a) const { return index <=> a.index; } ListIterator& operator++() { - ++pos; + ++index; return *this; } const HighLevelILOperand operator*(); }; HighLevelILInstruction m_instr; - const _STD_VECTOR& m_usageList; - const _STD_UNORDERED_MAP& m_operandIndexMap; + const HighLevelILOperandUsage* m_usages; + const uint8_t* m_indices; + uint8_t m_count; public: typedef ListIterator const_iterator; HighLevelILOperandList(const HighLevelILInstruction& instr, - const _STD_VECTOR& usageList, - const _STD_UNORDERED_MAP& operandIndexMap); + const HighLevelILOperandUsage* usages, + const uint8_t* indices, + uint8_t count); const_iterator begin() const; const_iterator end() const; diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 649c5c99f..036ef0937 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -18,7 +18,12 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. +#include #include +#include + +#include "sharedilinstruction.h" + #ifdef BINARYNINJACORE_LIBRARY #include "lowlevelilfunction.h" #include "lowlevelilssafunction.h" @@ -36,279 +41,304 @@ using namespace std; #endif -unordered_map LowLevelILInstructionBase::operandTypeForUsage = { - {SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, - {SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, - {SourceRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, - {SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, - {SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {SourceSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, - {SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, {DestExprLowLevelOperandUsage, ExprLowLevelOperand}, - {DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, - {DestRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, - {DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, - {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, - {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, - {SemanticFlagClassLowLevelOperandUsage, SemanticFlagClassLowLevelOperand}, - {SemanticFlagGroupLowLevelOperandUsage, SemanticFlagGroupLowLevelOperand}, - {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, - {PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, - {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, - {TopSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, {RightExprLowLevelOperandUsage, ExprLowLevelOperand}, - {CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, {ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, - {HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, - {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, - {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, - {IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand}, {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, - {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, - {TargetLowLevelOperandUsage, IndexLowLevelOperand}, {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, - {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, {BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, - {SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, - {DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, - {FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, - {OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, - {OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, - {ParameterExprsLowLevelOperandUsage, ExprListLowLevelOperand}, - {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, - {SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand}, - {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, - {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, - {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, - {OutputMemoryIntrinsicLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, - {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, - {TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, - {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}, - {ConstraintLowLevelOperandUsage, ConstraintLowLevelOperand}}; - - -unordered_map> LowLevelILInstructionBase::operationOperandUsage = - {{LLIL_NOP, {}}, {LLIL_POP, {}}, {LLIL_NORET, {}}, {LLIL_SYSCALL, {}}, {LLIL_BP, {}}, {LLIL_UNDEF, {}}, - {LLIL_UNIMPL, {}}, {LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_SPLIT, - {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_SSA_PARTIAL, - {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_SPLIT_SSA, - {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_STACK_REL, - {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_REG_STACK_PUSH, {DestRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_STACK_REL_SSA, - {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, - DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_REG_STACK_ABS_SSA, - {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, - DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_FORCE_VER, {DestRegisterLowLevelOperandUsage}}, - {LLIL_FORCE_VER_SSA, {DestSSARegisterLowLevelOperandUsage, SourceSSARegisterLowLevelOperandUsage}}, - {LLIL_ASSERT, {SourceRegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, - {LLIL_ASSERT_SSA, {SourceSSARegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, - {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, - {LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, - {LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, - SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, {LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, - {LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, - {LLIL_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage}}, - {LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}}, - {LLIL_REG_STACK_REL, {SourceRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, - {LLIL_REG_STACK_POP, {SourceRegisterStackLowLevelOperandUsage}}, - {LLIL_REG_STACK_FREE_REG, {DestRegisterLowLevelOperandUsage}}, - {LLIL_REG_STACK_FREE_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage}}, - {LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, - SourceExprLowLevelOperandUsage}}, - {LLIL_REG_STACK_ABS_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage}}, - {LLIL_REG_STACK_FREE_REL_SSA, - {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, - DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage}}, - {LLIL_REG_STACK_FREE_ABS_SSA, - {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, - DestRegisterLowLevelOperandUsage}}, - {LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, - {LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, - {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, - {LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, - {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, - {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetsLowLevelOperandUsage}}, - {LLIL_CALL, {DestExprLowLevelOperandUsage}}, - {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, - RegisterStackAdjustmentsLowLevelOperandUsage}}, - {LLIL_TAILCALL, {DestExprLowLevelOperandUsage}}, {LLIL_RET, {DestExprLowLevelOperandUsage}}, - {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, - {LLIL_GOTO, {TargetLowLevelOperandUsage}}, - {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage, SemanticFlagClassLowLevelOperandUsage}}, - {LLIL_FLAG_GROUP, {SemanticFlagGroupLowLevelOperandUsage}}, {LLIL_TRAP, {VectorLowLevelOperandUsage}}, - {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, - DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, - StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, - {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, - StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, - ParameterExprsLowLevelOperandUsage}}, - {LLIL_TAILCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, - DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, - StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, - {LLIL_SEPARATE_PARAM_LIST_SSA, {ParameterExprsLowLevelOperandUsage}}, - {LLIL_SHARED_PARAM_SLOT_SSA, {ParameterExprsLowLevelOperandUsage}}, - {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, - {LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, - {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, - {LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, - {LLIL_CONST, {ConstantLowLevelOperandUsage}}, {LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, - {LLIL_EXTERN_PTR, {ConstantLowLevelOperandUsage, OffsetLowLevelOperandUsage}}, - {LLIL_FLOAT_CONST, {ConstantLowLevelOperandUsage}}, - {LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, - {LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, - {LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, - {LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, - {LLIL_DIVU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_DIVS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, {LLIL_NEG, {SourceExprLowLevelOperandUsage}}, - {LLIL_NOT, {SourceExprLowLevelOperandUsage}}, {LLIL_SX, {SourceExprLowLevelOperandUsage}}, - {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, - {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, - {LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, - ParameterExprsLowLevelOperandUsage}}, - {LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, - ParameterExprsLowLevelOperandUsage}}, - {LLIL_MEMORY_INTRINSIC_SSA, {OutputMemoryIntrinsicLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, - ParameterExprsLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, - {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, - {LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FMUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FDIV, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FSQRT, {SourceExprLowLevelOperandUsage}}, {LLIL_FNEG, {SourceExprLowLevelOperandUsage}}, - {LLIL_FABS, {SourceExprLowLevelOperandUsage}}, {LLIL_FLOAT_TO_INT, {SourceExprLowLevelOperandUsage}}, - {LLIL_INT_TO_FLOAT, {SourceExprLowLevelOperandUsage}}, {LLIL_FLOAT_CONV, {SourceExprLowLevelOperandUsage}}, - {LLIL_ROUND_TO_INT, {SourceExprLowLevelOperandUsage}}, {LLIL_FLOOR, {SourceExprLowLevelOperandUsage}}, - {LLIL_CEIL, {SourceExprLowLevelOperandUsage}}, {LLIL_FTRUNC, {SourceExprLowLevelOperandUsage}}, - {LLIL_FCMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_LT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_LE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_GE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_GT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_O, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_FCMP_UO, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}}; - - -static unordered_map> - GetOperandIndexForOperandUsages() -{ - unordered_map> result; - result.reserve(LowLevelILInstructionBase::operationOperandUsage.size()); - for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) +namespace { + +struct OperandUsageType +{ + LowLevelILOperandUsage usage; + LowLevelILOperandType type; + + constexpr auto operator<=>(const OperandUsageType& other) const { - result[operation.first] = unordered_map(); + return usage <=> other.usage; + } +}; + +static constexpr std::array s_operandTypeForUsage = { + OperandUsageType{SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + OperandUsageType{SourceRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, + OperandUsageType{SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, + OperandUsageType{SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{SourceSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, + OperandUsageType{SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + OperandUsageType{DestExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + OperandUsageType{DestRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, + OperandUsageType{DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, + OperandUsageType{DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, + OperandUsageType{DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + OperandUsageType{SemanticFlagClassLowLevelOperandUsage, SemanticFlagClassLowLevelOperand}, + OperandUsageType{SemanticFlagGroupLowLevelOperandUsage, SemanticFlagGroupLowLevelOperand}, + OperandUsageType{PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + OperandUsageType{PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, + OperandUsageType{StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{TopSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{RightExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, + OperandUsageType{HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + OperandUsageType{HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + OperandUsageType{LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + OperandUsageType{IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand}, + OperandUsageType{ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, + OperandUsageType{VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + OperandUsageType{StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, + OperandUsageType{TargetLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, + OperandUsageType{OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + OperandUsageType{OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + OperandUsageType{ParameterExprsLowLevelOperandUsage, ExprListLowLevelOperand}, + OperandUsageType{SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + OperandUsageType{SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand}, + OperandUsageType{SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + OperandUsageType{OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, + OperandUsageType{OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, + OperandUsageType{OutputMemoryIntrinsicLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, + OperandUsageType{SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, + OperandUsageType{TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, + OperandUsageType{RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}, + OperandUsageType{OffsetLowLevelOperandUsage, IntegerLowLevelOperand}, + OperandUsageType{ConstraintLowLevelOperandUsage, ConstraintLowLevelOperand} +}; + +static_assert(std::is_sorted(s_operandTypeForUsage.begin(), s_operandTypeForUsage.end()), + "Operand type mapping array is not sorted by usage value"); + + +constexpr inline LowLevelILOperandType OperandTypeForUsage(LowLevelILOperandUsage usage) +{ + if (static_cast(usage) < s_operandTypeForUsage.size()) + return s_operandTypeForUsage[usage].type; + + throw LowLevelILInstructionAccessException(); +} + + +struct LowLevelILOperationTraits +{ + using ILOperation = BNLowLevelILOperation; + using OperandUsage = LowLevelILOperandUsage; + static constexpr size_t MaxOperands = 6; - size_t operand = 0; - result[operation.first].reserve(operation.second.size()); - for (auto usage : operation.second) + static constexpr bool OperandTypeRequiresTwoSlots(LowLevelILOperandType type) + { + switch (type) { - result[operation.first][usage] = operand; - switch (usage) - { - case HighSSARegisterLowLevelOperandUsage: - case LowSSARegisterLowLevelOperandUsage: - case PartialSSARegisterStackSourceLowLevelOperandUsage: - case TopSSARegisterLowLevelOperandUsage: - // Represented as subexpression, so only takes one slot even though it is an SSA register - operand++; - break; - case ParameterExprsLowLevelOperandUsage: - if (operand == 0) - { - // Represented as a counted list - operand += 2; - } - else - { - // Represented as subexpression, so only takes one slot even though it is a list - operand++; - } - break; - case OutputSSARegistersLowLevelOperandUsage: - // OutputMemoryVersionLowLevelOperandUsage follows at same operand - break; - case StackSSARegisterLowLevelOperandUsage: - // StackMemoryVersionLowLevelOperandUsage follows at same operand - break; - case DestSSARegisterStackLowLevelOperandUsage: - // PartialSSARegisterStackSourceLowLevelOperandUsage follows at same operand - break; - case OutputMemoryIntrinsicLowLevelOperandUsage: - // OutputMemoryVersionLowLevelOperandUsage follows at same operand - break; - default: - switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) - { - case SSARegisterLowLevelOperand: - case SSARegisterStackLowLevelOperand: - case SSAFlagLowLevelOperand: - case IndexListLowLevelOperand: - case IndexMapLowLevelOperand: - case SSARegisterListLowLevelOperand: - case SSARegisterStackListLowLevelOperand: - case SSAFlagListLowLevelOperand: - case RegisterStackAdjustmentsLowLevelOperand: - case RegisterOrFlagListLowLevelOperand: - case SSARegisterOrFlagListLowLevelOperand: - // SSA registers/flags and lists take two operand slots - operand += 2; - break; - default: - operand++; - break; - } - break; - } + case SSARegisterLowLevelOperand: + case SSARegisterStackLowLevelOperand: + case SSAFlagLowLevelOperand: + case IndexListLowLevelOperand: + case IndexMapLowLevelOperand: + case SSARegisterListLowLevelOperand: + case SSARegisterStackListLowLevelOperand: + case SSAFlagListLowLevelOperand: + case RegisterStackAdjustmentsLowLevelOperand: + case RegisterOrFlagListLowLevelOperand: + case SSARegisterOrFlagListLowLevelOperand: + case ExprListLowLevelOperand: + return true; + default: + return false; } } - return result; -} + static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t operandIndex) + { + // ParameterExprs at index 0 is a counted list and takes two slots + if (operandIndex == 0 && usage == ParameterExprsLowLevelOperandUsage) + return 2; + + switch (usage) + { + // Subexpressions take one slot + case HighSSARegisterLowLevelOperandUsage: + case LowSSARegisterLowLevelOperandUsage: + case PartialSSARegisterStackSourceLowLevelOperandUsage: + case TopSSARegisterLowLevelOperandUsage: + return 1; + + // ParameterExprs takes one slot when not at index 0 + case ParameterExprsLowLevelOperandUsage: + return 1; + + // The next operand follows at same index + case OutputSSARegistersLowLevelOperandUsage: + case StackSSARegisterLowLevelOperandUsage: + case DestSSARegisterStackLowLevelOperandUsage: + case OutputMemoryIntrinsicLowLevelOperandUsage: + return 0; -unordered_map> - LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + default: + return OperandTypeRequiresTwoSlots(OperandTypeForUsage(usage)) ? 2 : 1; + } + } +}; + +using OperandUsage = detail::ILInstructionOperandUsage; +static_assert(sizeof(OperandUsage) == 14); + + +static constexpr std::array s_instructionOperandUsage = { + OperandUsage{LLIL_NOP}, + OperandUsage{LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_STACK_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_PUSH, {DestRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ASSERT, {SourceRegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, + OperandUsage{LLIL_FORCE_VER, {DestRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_POP}, + OperandUsage{LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_REL, {SourceRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_POP, {SourceRegisterStackLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_FREE_REG, {DestRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_FREE_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CONST, {ConstantLowLevelOperandUsage}}, + OperandUsage{LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, + OperandUsage{LLIL_EXTERN_PTR, {ConstantLowLevelOperandUsage, OffsetLowLevelOperandUsage}}, + OperandUsage{LLIL_FLOAT_CONST, {ConstantLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + OperandUsage{LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + OperandUsage{LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_DIVU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_DIVS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MODU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_MODS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_NEG, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_NOT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SX, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ZX, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_JUMP, {DestExprLowLevelOperandUsage}}, + OperandUsage{LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetsLowLevelOperandUsage}}, + OperandUsage{LLIL_CALL, {DestExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage}}, + OperandUsage{LLIL_TAILCALL, {DestExprLowLevelOperandUsage}}, + OperandUsage{LLIL_RET, {DestExprLowLevelOperandUsage}}, + OperandUsage{LLIL_NORET}, + OperandUsage{LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, + OperandUsage{LLIL_GOTO, {TargetLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage, SemanticFlagClassLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_GROUP, {SemanticFlagGroupLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SYSCALL}, + OperandUsage{LLIL_BP}, + OperandUsage{LLIL_TRAP, {VectorLowLevelOperandUsage}}, + OperandUsage{LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_UNDEF}, + OperandUsage{LLIL_UNIMPL}, + OperandUsage{LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FMUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FDIV, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FSQRT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FNEG, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FABS, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FLOAT_TO_INT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_INT_TO_FLOAT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FLOAT_CONV, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ROUND_TO_INT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FLOOR, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CEIL, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FTRUNC, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_LT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_LE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_GE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_GT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_O, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_FCMP_UO, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_SSA_PARTIAL, {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_STACK_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_REG_STACK_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_SPLIT_DEST_SSA}, + OperandUsage{LLIL_REG_STACK_DEST_SSA}, + OperandUsage{LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_ABS_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_FREE_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_FREE_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_ASSERT_SSA, {SourceSSARegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, + OperandUsage{LLIL_FORCE_VER_SSA, {DestSSARegisterLowLevelOperandUsage, SourceSSARegisterLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + OperandUsage{LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_TAILCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_CALL_PARAM}, + OperandUsage{LLIL_CALL_STACK_SSA}, + OperandUsage{LLIL_CALL_OUTPUT_SSA}, + OperandUsage{LLIL_SEPARATE_PARAM_LIST_SSA, {ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_SHARED_PARAM_SLOT_SSA, {ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_MEMORY_INTRINSIC_OUTPUT_SSA}, + OperandUsage{LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, + OperandUsage{LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + OperandUsage{LLIL_MEMORY_INTRINSIC_SSA, {OutputMemoryIntrinsicLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, + OperandUsage{LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, + OperandUsage{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, + OperandUsage{LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, +}; + + +VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage); + + +} // unnamed namespace RegisterOrFlag::RegisterOrFlag() : isFlag(false), index(BN_INVALID_REGISTER) {} @@ -1115,12 +1145,8 @@ LowLevelILSSARegisterOrFlagList::operator vector() const LowLevelILOperand::LowLevelILOperand( const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, size_t operandIndex) : m_instr(instr), - m_usage(usage), m_operandIndex(operandIndex) + m_usage(usage), m_type(OperandTypeForUsage(usage)), m_operandIndex(operandIndex) { - auto i = LowLevelILInstructionBase::operandTypeForUsage.find(m_usage); - if (i == LowLevelILInstructionBase::operandTypeForUsage.end()) - throw LowLevelILInstructionAccessException(); - m_type = i->second; } @@ -1315,19 +1341,20 @@ map LowLevelILOperand::GetRegisterStackAdjustments() const const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() { - LowLevelILOperandUsage usage = *pos; - auto i = owner->m_operandIndexMap.find(usage); - if (i == owner->m_operandIndexMap.end()) + if (index >= owner->m_count) throw LowLevelILInstructionAccessException(); - return LowLevelILOperand(owner->m_instr, usage, i->second); + LowLevelILOperandUsage usage = owner->m_usages[index]; + size_t operandIndex = owner->m_indices[index]; + return LowLevelILOperand(owner->m_instr, usage, operandIndex); } LowLevelILOperandList::LowLevelILOperandList(const LowLevelILInstruction& instr, - const vector& usageList, - const unordered_map& operandIndexMap) : + const LowLevelILOperandUsage* usages, + const uint8_t* indices, + uint8_t count) : m_instr(instr), - m_usageList(usageList), m_operandIndexMap(operandIndexMap) + m_usages(usages), m_indices(indices), m_count(count) {} @@ -1335,7 +1362,7 @@ LowLevelILOperandList::const_iterator LowLevelILOperandList::begin() const { const_iterator result; result.owner = this; - result.pos = m_usageList.begin(); + result.index = 0; return result; } @@ -1344,24 +1371,24 @@ LowLevelILOperandList::const_iterator LowLevelILOperandList::end() const { const_iterator result; result.owner = this; - result.pos = m_usageList.end(); + result.index = m_count; return result; } size_t LowLevelILOperandList::size() const { - return m_usageList.size(); + return m_count; } const LowLevelILOperand LowLevelILOperandList::operator[](size_t i) const { - LowLevelILOperandUsage usage = m_usageList[i]; - auto indexMap = m_operandIndexMap.find(usage); - if (indexMap == m_operandIndexMap.end()) + if (i >= m_count) throw LowLevelILInstructionAccessException(); - return LowLevelILOperand(m_instr, usage, indexMap->second); + LowLevelILOperandUsage usage = m_usages[i]; + size_t operandIndex = m_indices[i]; + return LowLevelILOperand(m_instr, usage, operandIndex); } @@ -1428,13 +1455,11 @@ LowLevelILInstruction::LowLevelILInstruction(const LowLevelILInstructionBase& in LowLevelILOperandList LowLevelILInstructionBase::GetOperands() const { - auto usage = operationOperandUsage.find(operation); - if (usage == operationOperandUsage.end()) - throw LowLevelILInstructionAccessException(); - auto operandIndex = operationOperandIndex.find(operation); - if (operandIndex == operationOperandIndex.end()) + if (operation >= s_instructionOperandUsage.size()) throw LowLevelILInstructionAccessException(); - return LowLevelILOperandList(*(const LowLevelILInstruction*)this, usage->second, operandIndex->second); + + const auto& info = s_instructionOperandUsage[operation]; + return LowLevelILOperandList(*(const LowLevelILInstruction*)this, info.usages, info.indices, info.count); } @@ -2384,14 +2409,19 @@ ExprId LowLevelILInstruction::CopyTo( bool LowLevelILInstruction::GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const { - auto operationIter = LowLevelILInstructionBase::operationOperandIndex.find(operation); - if (operationIter == LowLevelILInstructionBase::operationOperandIndex.end()) + if (operation >= s_instructionOperandUsage.size()) return false; - auto usageIter = operationIter->second.find(usage); - if (usageIter == operationIter->second.end()) - return false; - operandIndex = usageIter->second; - return true; + + const auto& info = s_instructionOperandUsage[operation]; + for (uint8_t i = 0; i < info.count; i++) + { + if (info.usages[i] == usage) + { + operandIndex = info.indices[i]; + return true; + } + } + return false; } diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 4c3499b81..37d0d30a8 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -162,7 +162,7 @@ namespace BinaryNinja /*! \ingroup lowlevelil */ - enum LowLevelILOperandType + enum LowLevelILOperandType : uint8_t { IntegerLowLevelOperand, IndexLowLevelOperand, @@ -192,7 +192,7 @@ namespace BinaryNinja /*! \ingroup lowlevelil */ - enum LowLevelILOperandUsage + enum LowLevelILOperandUsage : uint8_t { SourceExprLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage, @@ -750,11 +750,6 @@ namespace BinaryNinja #endif size_t exprIndex, instructionIndex; - static _STD_UNORDERED_MAP operandTypeForUsage; - static _STD_UNORDERED_MAP> operationOperandUsage; - static _STD_UNORDERED_MAP> - operationOperandIndex; - LowLevelILOperandList GetOperands() const; uint64_t GetRawOperandAsInteger(size_t operand) const; @@ -1290,27 +1285,27 @@ namespace BinaryNinja typedef value_type reference; const LowLevelILOperandList* owner; - _STD_VECTOR::const_iterator pos; - bool operator==(const ListIterator& a) const { return pos == a.pos; } - bool operator!=(const ListIterator& a) const { return pos != a.pos; } - bool operator<(const ListIterator& a) const { return pos < a.pos; } + size_t index; + constexpr bool operator==(const ListIterator& a) const { return index == a.index; } + constexpr auto operator<=>(const ListIterator& a) const { return index <=> a.index; } ListIterator& operator++() { - ++pos; + ++index; return *this; } const LowLevelILOperand operator*(); }; LowLevelILInstruction m_instr; - const _STD_VECTOR& m_usageList; - const _STD_UNORDERED_MAP& m_operandIndexMap; + const LowLevelILOperandUsage* m_usages; + const uint8_t* m_indices; + uint8_t m_count; public: typedef ListIterator const_iterator; - LowLevelILOperandList(const LowLevelILInstruction& instr, const _STD_VECTOR& usageList, - const _STD_UNORDERED_MAP& operandIndexMap); + LowLevelILOperandList(const LowLevelILInstruction& instr, const LowLevelILOperandUsage* usages, + const uint8_t* indices, uint8_t count); const_iterator begin() const; const_iterator end() const; diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 1cbabb5e8..b1b9d7d6d 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -18,7 +18,12 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. +#include +#include #include + +#include "sharedilinstruction.h" + #ifdef BINARYNINJACORE_LIBRARY #include "mediumlevelilfunction.h" #include "mediumlevelilssafunction.h" @@ -35,276 +40,263 @@ using namespace BinaryNinja; using namespace std; #endif +namespace { + +struct OperandUsageType +{ + MediumLevelILOperandUsage usage; + MediumLevelILOperandType type; -unordered_map MediumLevelILInstructionBase::operandTypeForUsage = { - {SourceExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {SourceVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {SourceSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, - {PartialSSAVariableSourceMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, - {DestExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {DestVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {DestSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, - {LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, - {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, - {ConstantDataMediumLevelOperandUsage, ConstantDataMediumLevelOperand}, - {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, - {IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand}, - {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, - {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, - {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, - {DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {TargetsMediumLevelOperandUsage, IndexMapMediumLevelOperand}, - {SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, - {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, - {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, - {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, - {OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, - {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, - {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, - {UntypedParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, - {UntypedParameterSSAExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, - {ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand}, - {ConstraintMediumLevelOperandUsage, ConstraintMediumLevelOperand}}; - - -unordered_map> - MediumLevelILInstructionBase::operationOperandUsage = {{MLIL_NOP, {}}, {MLIL_NORET, {}}, {MLIL_BP, {}}, - {MLIL_UNDEF, {}}, {MLIL_UNIMPL, {}}, - {MLIL_SET_VAR, {DestVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_FIELD, - {DestVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage, - SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_SSA_FIELD, - {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, - OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage, - SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, - SourceExprMediumLevelOperandUsage}}, - {MLIL_SET_VAR_ALIASED_FIELD, - {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, - OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_FORCE_VER, {DestVariableMediumLevelOperandUsage, SourceVariableMediumLevelOperandUsage}}, - {MLIL_FORCE_VER_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariableMediumLevelOperandUsage}}, - {MLIL_ASSERT, {SourceVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, - {MLIL_ASSERT_SSA, {SourceSSAVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, - {MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, - {MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, - SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_STORE, {DestExprMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_STORE_STRUCT, - {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, - SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_STORE_STRUCT_SSA, - {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, - SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, - {MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, - {MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage}}, - {MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, - {MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, - {MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage}}, - {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, - {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, - {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetsMediumLevelOperandUsage}}, - {MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, - {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage}}, - {MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - UntypedParameterExprsMediumLevelOperandUsage}}, - {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, - UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - {MLIL_TAILCALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage}}, - {MLIL_TAILCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - UntypedParameterExprsMediumLevelOperandUsage}}, - {MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, - OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_CALL_UNTYPED_SSA, - {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, - DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, - ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - {MLIL_SYSCALL_SSA, - {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_SYSCALL_UNTYPED_SSA, - {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, - UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, - StackExprMediumLevelOperandUsage}}, - {MLIL_TAILCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, - OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_TAILCALL_UNTYPED_SSA, - {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, - DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, - ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - {MLIL_SEPARATE_PARAM_LIST, {ParameterExprsMediumLevelOperandUsage}}, - {MLIL_SHARED_PARAM_SLOT, {ParameterExprsMediumLevelOperandUsage}}, - {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, - {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, - FalseTargetMediumLevelOperandUsage}}, - {MLIL_GOTO, {TargetMediumLevelOperandUsage}}, - {MLIL_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage}}, - {MLIL_INTRINSIC_SSA, {OutputSSAVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage}}, - {MLIL_MEMORY_INTRINSIC_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, - ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, - {MLIL_FREE_VAR_SLOT_SSA, - {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage}}, - {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, - {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, - {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, - {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, - {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, - {MLIL_EXTERN_PTR, {ConstantMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - {MLIL_FLOAT_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, - {MLIL_CONST_DATA, {ConstantDataMediumLevelOperandUsage}}, - {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_OR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_XOR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_LSL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_LSR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_ASR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_ROL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_ROR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MULU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MULS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_DIVU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_DIVS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MODU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MODS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_SLT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_ULT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_SLE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_ULE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_SGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_UGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_SGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_CMP_UGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_ADC, - {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, - {MLIL_SBB, - {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, - {MLIL_RLC, - {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, - {MLIL_RRC, - {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, - {MLIL_DIVU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_DIVS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MODU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_MODS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, {MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, - {MLIL_SX, {SourceExprMediumLevelOperandUsage}}, {MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, - {MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, {MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, - {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}}, - {MLIL_FADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FSUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FMUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FDIV, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FSQRT, {SourceExprMediumLevelOperandUsage}}, {MLIL_FNEG, {SourceExprMediumLevelOperandUsage}}, - {MLIL_FABS, {SourceExprMediumLevelOperandUsage}}, {MLIL_FLOAT_TO_INT, {SourceExprMediumLevelOperandUsage}}, - {MLIL_INT_TO_FLOAT, {SourceExprMediumLevelOperandUsage}}, - {MLIL_FLOAT_CONV, {SourceExprMediumLevelOperandUsage}}, - {MLIL_ROUND_TO_INT, {SourceExprMediumLevelOperandUsage}}, {MLIL_FLOOR, {SourceExprMediumLevelOperandUsage}}, - {MLIL_CEIL, {SourceExprMediumLevelOperandUsage}}, {MLIL_FTRUNC, {SourceExprMediumLevelOperandUsage}}, - {MLIL_FCMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_LT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_LE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_GE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_GT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_O, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - {MLIL_FCMP_UO, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}}; - - -static unordered_map> - GetOperandIndexForOperandUsages() -{ - unordered_map> result; - result.reserve(MediumLevelILInstructionBase::operationOperandUsage.size()); - for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) + constexpr auto operator<=>(const OperandUsageType& other) const { - result[operation.first] = unordered_map(); - result[operation.first].reserve(operation.second.size()); - size_t operand = 0; - for (auto usage : operation.second) + return usage <=> other.usage; + } +}; + +static constexpr std::array s_operandTypeForUsage = { + OperandUsageType{SourceExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{SourceVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{SourceSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + OperandUsageType{PartialSSAVariableSourceMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + OperandUsageType{DestExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{DestVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{DestSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + OperandUsageType{LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + OperandUsageType{HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, + OperandUsageType{ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, + OperandUsageType{ConstantDataMediumLevelOperandUsage, ConstantDataMediumLevelOperand}, + OperandUsageType{VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + OperandUsageType{IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand}, + OperandUsageType{TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{TargetsMediumLevelOperandUsage, IndexMapMediumLevelOperand}, + OperandUsageType{SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, + OperandUsageType{OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + OperandUsageType{OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, + OperandUsageType{OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + OperandUsageType{OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + OperandUsageType{OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + OperandUsageType{SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + OperandUsageType{UntypedParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + OperandUsageType{UntypedParameterSSAExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + OperandUsageType{ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + OperandUsageType{SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand}, + OperandUsageType{ConstraintMediumLevelOperandUsage, ConstraintMediumLevelOperand}, +}; + +static_assert(std::is_sorted(s_operandTypeForUsage.begin(), s_operandTypeForUsage.end()), + "Operand type mapping array is not sorted by usage value"); + +constexpr inline MediumLevelILOperandType OperandTypeForUsage(MediumLevelILOperandUsage usage) +{ + if (static_cast(usage) < s_operandTypeForUsage.size()) + return s_operandTypeForUsage[usage].type; + + throw MediumLevelILInstructionAccessException(); +} + +struct MediumLevelILOperationTraits +{ + using ILOperation = BNMediumLevelILOperation; + using OperandUsage = MediumLevelILOperandUsage; + static constexpr size_t MaxOperands = 6; + + static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t operandIndex) + { + switch (usage) { - result[operation.first][usage] = operand; - switch (usage) - { - case PartialSSAVariableSourceMediumLevelOperandUsage: - // SSA variables are usually two slots, but this one has a previously defined - // variables and thus only takes one slot - operand++; - break; - case OutputVariablesSubExprMediumLevelOperandUsage: - case UntypedParameterExprsMediumLevelOperandUsage: - // Represented as subexpression, so only takes one slot even though it is a list - operand++; - break; - case OutputSSAVariablesSubExprMediumLevelOperandUsage: - // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand - break; - case UntypedParameterSSAExprsMediumLevelOperandUsage: - // ParameterSSAMemoryVersionMediumLevelOperandUsage follows at same operand - break; + case PartialSSAVariableSourceMediumLevelOperandUsage: + // SSA variables are usually two slots, but this one has a previously defined + // variables and thus only takes one slot + return 1; + case OutputVariablesSubExprMediumLevelOperandUsage: + case UntypedParameterExprsMediumLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + return 1; + case OutputSSAVariablesSubExprMediumLevelOperandUsage: + // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand + return 0; + case UntypedParameterSSAExprsMediumLevelOperandUsage: + // ParameterSSAMemoryVersionMediumLevelOperandUsage follows at same operand + return 0; + default: + switch (OperandTypeForUsage(usage)) { + case SSAVariableMediumLevelOperand: + case IndexListMediumLevelOperand: + case IndexMapMediumLevelOperand: + case VariableListMediumLevelOperand: + case SSAVariableListMediumLevelOperand: + case ExprListMediumLevelOperand: + return 2; default: - switch (MediumLevelILInstructionBase::operandTypeForUsage[usage]) - { - case SSAVariableMediumLevelOperand: - case IndexListMediumLevelOperand: - case IndexMapMediumLevelOperand: - case VariableListMediumLevelOperand: - case SSAVariableListMediumLevelOperand: - case ExprListMediumLevelOperand: - // SSA variables and lists take two operand slots - operand += 2; - break; - default: - operand++; - break; - } - break; + return 1; } } } - return result; -} - - -unordered_map> - MediumLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); +}; + +using OperandUsage = detail::ILInstructionOperandUsage; +static_assert(sizeof(OperandUsage) == 14); + + +static constexpr std::array s_instructionOperandUsage = { + OperandUsage{MLIL_NOP}, + OperandUsage{MLIL_SET_VAR, {DestVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_FIELD, {DestVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ASSERT, {SourceVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, + OperandUsage{MLIL_FORCE_VER, {DestVariableMediumLevelOperandUsage, SourceVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_STORE, {DestExprMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_STORE_STRUCT, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_CONST, {ConstantMediumLevelOperandUsage}}, + OperandUsage{MLIL_CONST_DATA, {ConstantDataMediumLevelOperandUsage}}, + OperandUsage{MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + OperandUsage{MLIL_EXTERN_PTR, {ConstantMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_FLOAT_CONST, {ConstantMediumLevelOperandUsage}}, + OperandUsage{MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, + OperandUsage{MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ADC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SBB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_OR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_XOR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_LSL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_LSR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ASR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ROL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_RLC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ROR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_RRC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MULU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MULS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_DIVU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_DIVU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_DIVS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_DIVS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MODU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MODU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MODS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_MODS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SX, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetsMediumLevelOperandUsage}}, + OperandUsage{MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_OUTPUT, {OutputVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_PARAM, {ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_SEPARATE_PARAM_LIST, {ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_SHARED_PARAM_SLOT, {ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_NORET}, + OperandUsage{MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage}}, + OperandUsage{MLIL_GOTO, {TargetMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_SLT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_ULT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_SLE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_ULE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_SGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_UGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_SGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CMP_UGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_TAILCALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_TAILCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_BP}, + OperandUsage{MLIL_TRAP, {VectorMediumLevelOperandUsage}}, + OperandUsage{MLIL_UNDEF}, + OperandUsage{MLIL_UNIMPL}, + OperandUsage{MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FSUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FMUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FDIV, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FSQRT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FNEG, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FABS, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FLOAT_TO_INT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_INT_TO_FLOAT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FLOAT_CONV, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_ROUND_TO_INT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FLOOR, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CEIL, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FTRUNC, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_LT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_LE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_GE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_GT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_O, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_FCMP_UO, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_SSA_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SET_VAR_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_ASSERT_SSA, {SourceSSAVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, + OperandUsage{MLIL_FORCE_VER_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariableMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SYSCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_TAILCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_TAILCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_PARAM_SSA, {ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_OUTPUT_SSA, {OutputSSAVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, {OutputSSAVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_STORE_STRUCT_SSA, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_INTRINSIC_SSA, {OutputSSAVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_MEMORY_INTRINSIC_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_FREE_VAR_SLOT_SSA, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, + OperandUsage{MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, +}; + +VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage); + +} // anonymous namespace bool MediumLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const @@ -689,12 +681,8 @@ MediumLevelILInstructionList::operator vector() const MediumLevelILOperand::MediumLevelILOperand( const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, size_t operandIndex) : m_instr(instr), - m_usage(usage), m_operandIndex(operandIndex) + m_usage(usage), m_type(OperandTypeForUsage(usage)), m_operandIndex(operandIndex) { - auto i = MediumLevelILInstructionBase::operandTypeForUsage.find(m_usage); - if (i == MediumLevelILInstructionBase::operandTypeForUsage.end()) - throw MediumLevelILInstructionAccessException(); - m_type = i->second; } @@ -809,19 +797,17 @@ MediumLevelILInstructionList MediumLevelILOperand::GetExprList() const const MediumLevelILOperand MediumLevelILOperandList::ListIterator::operator*() { - MediumLevelILOperandUsage usage = *pos; - auto i = owner->m_operandIndexMap.find(usage); - if (i == owner->m_operandIndexMap.end()) - throw MediumLevelILInstructionAccessException(); - return MediumLevelILOperand(owner->m_instr, usage, i->second); + MediumLevelILOperandUsage usage = owner->m_usages[index]; + size_t operandIndex = owner->m_indices[index]; + return MediumLevelILOperand(owner->m_instr, usage, operandIndex); } MediumLevelILOperandList::MediumLevelILOperandList(const MediumLevelILInstruction& instr, - const vector& usageList, - const unordered_map& operandIndexMap) : + const MediumLevelILOperandUsage* usages, + const uint8_t* indices, uint8_t count) : m_instr(instr), - m_usageList(usageList), m_operandIndexMap(operandIndexMap) + m_usages(usages), m_indices(indices), m_count(count) {} @@ -829,7 +815,7 @@ MediumLevelILOperandList::const_iterator MediumLevelILOperandList::begin() const { const_iterator result; result.owner = this; - result.pos = m_usageList.begin(); + result.index = 0; return result; } @@ -838,24 +824,24 @@ MediumLevelILOperandList::const_iterator MediumLevelILOperandList::end() const { const_iterator result; result.owner = this; - result.pos = m_usageList.end(); + result.index = m_count; return result; } size_t MediumLevelILOperandList::size() const { - return m_usageList.size(); + return m_count; } const MediumLevelILOperand MediumLevelILOperandList::operator[](size_t i) const { - MediumLevelILOperandUsage usage = m_usageList[i]; - auto indexMap = m_operandIndexMap.find(usage); - if (indexMap == m_operandIndexMap.end()) + if (i >= m_count) throw MediumLevelILInstructionAccessException(); - return MediumLevelILOperand(m_instr, usage, indexMap->second); + MediumLevelILOperandUsage usage = m_usages[i]; + size_t operandIndex = m_indices[i]; + return MediumLevelILOperand(m_instr, usage, operandIndex); } @@ -921,13 +907,11 @@ MediumLevelILInstruction::MediumLevelILInstruction(const MediumLevelILInstructio MediumLevelILOperandList MediumLevelILInstructionBase::GetOperands() const { - auto usage = operationOperandUsage.find(operation); - if (usage == operationOperandUsage.end()) + if (operation >= s_instructionOperandUsage.size()) throw MediumLevelILInstructionAccessException(); - auto operandIndex = operationOperandIndex.find(operation); - if (operandIndex == operationOperandIndex.end()) - throw MediumLevelILInstructionAccessException(); - return MediumLevelILOperandList(*(const MediumLevelILInstruction*)this, usage->second, operandIndex->second); + + const auto& info = s_instructionOperandUsage[operation]; + return MediumLevelILOperandList(*(const MediumLevelILInstruction*)this, info.usages, info.indices, info.count); } @@ -1919,14 +1903,19 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, bool MediumLevelILInstruction::GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const { - auto operationIter = MediumLevelILInstructionBase::operationOperandIndex.find(operation); - if (operationIter == MediumLevelILInstructionBase::operationOperandIndex.end()) - return false; - auto usageIter = operationIter->second.find(usage); - if (usageIter == operationIter->second.end()) + if (operation >= s_instructionOperandUsage.size()) return false; - operandIndex = usageIter->second; - return true; + + const auto& info = s_instructionOperandUsage[operation]; + for (uint8_t i = 0; i < info.count; i++) + { + if (info.usages[i] == usage) + { + operandIndex = info.indices[i]; + return true; + } + } + return false; } diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index ef1f90170..b3965a637 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -37,6 +37,10 @@ namespace BinaryNinjaCore namespace BinaryNinja #endif { +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + class MediumLevelILFunction; template @@ -85,7 +89,7 @@ namespace BinaryNinja /*! \ingroup mediumlevelil */ - enum MediumLevelILOperandType + enum MediumLevelILOperandType : uint8_t { IntegerMediumLevelOperand, ConstantDataMediumLevelOperand, @@ -105,7 +109,7 @@ namespace BinaryNinja /*! \ingroup mediumlevelil */ - enum MediumLevelILOperandUsage + enum MediumLevelILOperandUsage : uint8_t { SourceExprMediumLevelOperandUsage, SourceVariableMediumLevelOperandUsage, @@ -485,12 +489,6 @@ namespace BinaryNinja #endif size_t exprIndex, instructionIndex; - static _STD_UNORDERED_MAP operandTypeForUsage; - static _STD_UNORDERED_MAP> - operationOperandUsage; - static _STD_UNORDERED_MAP> - operationOperandIndex; - MediumLevelILOperandList GetOperands() const; uint64_t GetRawOperandAsInteger(size_t operand) const; @@ -932,28 +930,28 @@ namespace BinaryNinja typedef value_type reference; const MediumLevelILOperandList* owner; - _STD_VECTOR::const_iterator pos; - bool operator==(const ListIterator& a) const { return pos == a.pos; } - bool operator!=(const ListIterator& a) const { return pos != a.pos; } - bool operator<(const ListIterator& a) const { return pos < a.pos; } + size_t index; + constexpr bool operator==(const ListIterator& a) const { return index == a.index; } + constexpr auto operator<=>(const ListIterator& a) const { return index <=> a.index; } ListIterator& operator++() { - ++pos; + ++index; return *this; } const MediumLevelILOperand operator*(); }; MediumLevelILInstruction m_instr; - const _STD_VECTOR& m_usageList; - const _STD_UNORDERED_MAP& m_operandIndexMap; + const MediumLevelILOperandUsage* m_usages; + const uint8_t* m_indices; + uint8_t m_count; public: typedef ListIterator const_iterator; MediumLevelILOperandList(const MediumLevelILInstruction& instr, - const _STD_VECTOR& usageList, - const _STD_UNORDERED_MAP& operandIndexMap); + const MediumLevelILOperandUsage* usages, + const uint8_t* indices, uint8_t count); const_iterator begin() const; const_iterator end() const; diff --git a/sharedilinstruction.h b/sharedilinstruction.h new file mode 100644 index 000000000..5d47c9b3a --- /dev/null +++ b/sharedilinstruction.h @@ -0,0 +1,94 @@ +// Copyright (c) 2025 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include +#include +#include + +#ifdef BINARYNINJACORE_LIBRARY +#define BINARYNINJA_NAMESPACE BinaryNinjaCore +#else +#define BINARYNINJA_NAMESPACE BinaryNinja +#endif + +namespace BINARYNINJA_NAMESPACE ::detail { + + +template +struct ILInstructionOperandUsage +{ + using ILOperation = typename Traits::ILOperation; + using OperandUsage = typename Traits::OperandUsage; + static constexpr size_t MaxOperands = Traits::MaxOperands; + + ILOperation op; + uint8_t count = 0; + OperandUsage usages[MaxOperands] = {}; + uint8_t indices[MaxOperands] = {}; + + explicit constexpr ILInstructionOperandUsage(ILOperation op) + : op(op) {} + + template + constexpr ILInstructionOperandUsage(ILOperation op, const OperandUsage (&ops)[N]) + : op(op), count(N) + { + static_assert(N <= MaxOperands, "Too many operands for instruction"); + std::copy(ops, ops + N, usages); + + uint8_t index = 0; + for (size_t i = 0; i < N; i++) + { + indices[i] = index; + index += Traits::GetOperandIndexAdvance(ops[i], i); + } + } +}; + + +template +struct ArrayMismatchError +{ + static_assert(Expected == Actual, "Array entries out of order"); +}; + + +template +constexpr bool ValidateArrayOrdering() +{ + if constexpr (Index < array.size()) + { + using OperationType = decltype(array[0].op); + (void)ArrayMismatchError(Index), array[Index].op>{}; + return ValidateArrayOrdering(); + } + return true; +} + + +} // namespace BINARYNINJA_NAMESPACE ::detail + + +// Validate that the position of each instruction in `array` matches the value of its operation. +#define VALIDATE_INSTRUCTION_ORDER(array) \ + static_assert(BINARYNINJA_NAMESPACE ::detail::ValidateArrayOrdering(), \ + "Array entries out of order, see ArrayMismatchError for details")