summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--highlevelilinstruction.cpp471
-rw-r--r--highlevelilinstruction.h27
-rw-r--r--lowlevelilinstruction.cpp616
-rw-r--r--lowlevelilinstruction.h27
-rw-r--r--mediumlevelilinstruction.cpp567
-rw-r--r--mediumlevelilinstruction.h32
-rw-r--r--sharedilinstruction.h94
7 files changed, 985 insertions, 849 deletions
diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp
index 0861cf31..55df8d21 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 <string.h>
+#include <algorithm>
+#include <array>
+#include <cstring>
+
+#include "sharedilinstruction.h"
+
#ifdef BINARYNINJACORE_LIBRARY
#include "highlevelilfunction.h"
#include "highlevelilssafunction.h"
@@ -36,203 +41,230 @@ using namespace BinaryNinja;
using namespace std;
#endif
+namespace {
-unordered_map<HighLevelILOperandUsage, HighLevelILOperandType> 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}};
+struct OperandUsageType
+{
+ HighLevelILOperandUsage usage;
+ HighLevelILOperandType type;
+ constexpr auto operator<=>(const OperandUsageType& other) const
+ {
+ return usage <=> other.usage;
+ }
+};
-unordered_map<BNHighLevelILOperation, vector<HighLevelILOperandUsage>>
- 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 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<size_t>(usage) < s_operandTypeForUsage.size())
+ return s_operandTypeForUsage[usage].type;
+
+ throw HighLevelILInstructionAccessException();
+}
-static unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>>
- GetOperandIndexForOperandUsages()
+struct HighLevelILOperationTraits
{
- unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> result;
- result.reserve(HighLevelILInstructionBase::operationOperandUsage.size());
- for (auto& operation : HighLevelILInstructionBase::operationOperandUsage)
+ using ILOperation = BNHighLevelILOperation;
+ using OperandUsage = HighLevelILOperandUsage;
+ static constexpr size_t MaxOperands = 5;
+
+ static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t /* operandIndex */)
{
- result[operation.first] = unordered_map<HighLevelILOperandUsage, size_t>();
- result[operation.first].reserve(operation.second.size());
- size_t operand = 0;
- for (auto usage : operation.second)
+ switch (OperandTypeForUsage(usage))
{
- 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;
- }
+ case SSAVariableHighLevelOperand:
+ case SSAVariableListHighLevelOperand:
+ case ExprListHighLevelOperand:
+ case IndexListHighLevelOperand:
+ return 2;
+ default:
+ return 1;
}
}
- return result;
-}
+};
+using OperandUsage = detail::ILInstructionOperandUsage<HighLevelILOperationTraits>;
+static_assert(sizeof(OperandUsage) == 12);
-unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>>
- HighLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages();
+
+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<SSAVariable>() 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<HighLevelILOperandUsage>& usageList,
- const unordered_map<HighLevelILOperandUsage, size_t>& 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())
+ if (operation >= s_instructionOperandUsage.size())
throw HighLevelILInstructionAccessException();
- auto operandIndex = operationOperandIndex.find(operation);
- if (operandIndex == operationOperandIndex.end())
- 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())
+ 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/highlevelilinstruction.h b/highlevelilinstruction.h
index 53a3c567..84afeb98 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<HighLevelILOperandUsage, HighLevelILOperandType> operandTypeForUsage;
- static _STD_UNORDERED_MAP<BNHighLevelILOperation, _STD_VECTOR<HighLevelILOperandUsage>> operationOperandUsage;
- static _STD_UNORDERED_MAP<BNHighLevelILOperation, _STD_UNORDERED_MAP<HighLevelILOperandUsage, size_t>>
- operationOperandIndex;
HighLevelILOperandList GetOperands() const;
@@ -856,28 +852,29 @@ namespace BinaryNinja
typedef value_type reference;
const HighLevelILOperandList* owner;
- _STD_VECTOR<HighLevelILOperandUsage>::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<HighLevelILOperandUsage>& m_usageList;
- const _STD_UNORDERED_MAP<HighLevelILOperandUsage, size_t>& 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<HighLevelILOperandUsage>& usageList,
- const _STD_UNORDERED_MAP<HighLevelILOperandUsage, size_t>& 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 649c5c99..036ef093 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 <algorithm>
#include <cstring>
+#include <array>
+
+#include "sharedilinstruction.h"
+
#ifdef BINARYNINJACORE_LIBRARY
#include "lowlevelilfunction.h"
#include "lowlevelilssafunction.h"
@@ -36,279 +41,304 @@ using namespace std;
#endif
-unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> 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}};
+namespace {
+
+struct OperandUsageType
+{
+ LowLevelILOperandUsage usage;
+ LowLevelILOperandType type;
+
+ constexpr auto operator<=>(const OperandUsageType& other) const
+ {
+ 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<size_t>(usage) < s_operandTypeForUsage.size())
+ return s_operandTypeForUsage[usage].type;
-unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> 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}}};
+ throw LowLevelILInstructionAccessException();
+}
-static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>>
- GetOperandIndexForOperandUsages()
+struct LowLevelILOperationTraits
{
- unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> result;
- result.reserve(LowLevelILInstructionBase::operationOperandUsage.size());
- for (auto& operation : LowLevelILInstructionBase::operationOperandUsage)
+ using ILOperation = BNLowLevelILOperation;
+ using OperandUsage = LowLevelILOperandUsage;
+ static constexpr size_t MaxOperands = 6;
+
+ static constexpr bool OperandTypeRequiresTwoSlots(LowLevelILOperandType type)
+ {
+ switch (type)
+ {
+ 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;
+ }
+ }
+
+ static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t operandIndex)
{
- result[operation.first] = unordered_map<LowLevelILOperandUsage, size_t>();
+ // ParameterExprs at index 0 is a counted list and takes two slots
+ if (operandIndex == 0 && usage == ParameterExprsLowLevelOperandUsage)
+ return 2;
- size_t operand = 0;
- result[operation.first].reserve(operation.second.size());
- for (auto usage : operation.second)
+ switch (usage)
{
- 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;
- }
+ // 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;
+
+ default:
+ return OperandTypeRequiresTwoSlots(OperandTypeForUsage(usage)) ? 2 : 1;
}
}
- return result;
-}
+};
+
+using OperandUsage = detail::ILInstructionOperandUsage<LowLevelILOperationTraits>;
+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}},
+};
-unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>>
- LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages();
+
+VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage);
+
+
+} // unnamed namespace
RegisterOrFlag::RegisterOrFlag() : isFlag(false), index(BN_INVALID_REGISTER) {}
@@ -1115,12 +1145,8 @@ LowLevelILSSARegisterOrFlagList::operator vector<SSARegisterOrFlag>() 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<uint32_t, int32_t> 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<LowLevelILOperandUsage>& usageList,
- const unordered_map<LowLevelILOperandUsage, size_t>& 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 4c3499b8..37d0d30a 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<LowLevelILOperandUsage, LowLevelILOperandType> operandTypeForUsage;
- static _STD_UNORDERED_MAP<BNLowLevelILOperation, _STD_VECTOR<LowLevelILOperandUsage>> operationOperandUsage;
- static _STD_UNORDERED_MAP<BNLowLevelILOperation, _STD_UNORDERED_MAP<LowLevelILOperandUsage, size_t>>
- 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<LowLevelILOperandUsage>::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<LowLevelILOperandUsage>& m_usageList;
- const _STD_UNORDERED_MAP<LowLevelILOperandUsage, size_t>& 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<LowLevelILOperandUsage>& usageList,
- const _STD_UNORDERED_MAP<LowLevelILOperandUsage, size_t>& 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 1cbabb5e..b1b9d7d6 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 <algorithm>
+#include <array>
#include <cstring>
+
+#include "sharedilinstruction.h"
+
#ifdef BINARYNINJACORE_LIBRARY
#include "mediumlevelilfunction.h"
#include "mediumlevelilssafunction.h"
@@ -35,276 +40,263 @@ using namespace BinaryNinja;
using namespace std;
#endif
+namespace {
-unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> 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}};
+struct OperandUsageType
+{
+ MediumLevelILOperandUsage usage;
+ MediumLevelILOperandType type;
+ constexpr auto operator<=>(const OperandUsageType& other) const
+ {
+ return usage <=> other.usage;
+ }
+};
-unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>>
- 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 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");
-static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>>
- GetOperandIndexForOperandUsages()
+constexpr inline MediumLevelILOperandType OperandTypeForUsage(MediumLevelILOperandUsage usage)
{
- unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> result;
- result.reserve(MediumLevelILInstructionBase::operationOperandUsage.size());
- for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage)
+ if (static_cast<size_t>(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)
{
- result[operation.first] = unordered_map<MediumLevelILOperandUsage, size_t>();
- result[operation.first].reserve(operation.second.size());
- size_t operand = 0;
- for (auto usage : operation.second)
+ 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;
-}
+};
+
+using OperandUsage = detail::ILInstructionOperandUsage<MediumLevelILOperationTraits>;
+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}},
+};
-unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>>
- MediumLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages();
+VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage);
+
+} // anonymous namespace
bool MediumLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const
@@ -689,12 +681,8 @@ MediumLevelILInstructionList::operator vector<MediumLevelILInstruction>() 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<MediumLevelILOperandUsage>& usageList,
- const unordered_map<MediumLevelILOperandUsage, size_t>& 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 ef1f9017..b3965a63 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 <BNMediumLevelILOperation N>
@@ -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<MediumLevelILOperandUsage, MediumLevelILOperandType> operandTypeForUsage;
- static _STD_UNORDERED_MAP<BNMediumLevelILOperation, _STD_VECTOR<MediumLevelILOperandUsage>>
- operationOperandUsage;
- static _STD_UNORDERED_MAP<BNMediumLevelILOperation, _STD_UNORDERED_MAP<MediumLevelILOperandUsage, size_t>>
- 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<MediumLevelILOperandUsage>::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<MediumLevelILOperandUsage>& m_usageList;
- const _STD_UNORDERED_MAP<MediumLevelILOperandUsage, size_t>& 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<MediumLevelILOperandUsage>& usageList,
- const _STD_UNORDERED_MAP<MediumLevelILOperandUsage, size_t>& 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 00000000..5d47c9b3
--- /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 <stdint.h>
+#include <stddef.h>
+#include <algorithm>
+
+#ifdef BINARYNINJACORE_LIBRARY
+#define BINARYNINJA_NAMESPACE BinaryNinjaCore
+#else
+#define BINARYNINJA_NAMESPACE BinaryNinja
+#endif
+
+namespace BINARYNINJA_NAMESPACE ::detail {
+
+
+template <typename Traits>
+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 <size_t N>
+ 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 <size_t Index, auto Expected, auto Actual>
+struct ArrayMismatchError
+{
+ static_assert(Expected == Actual, "Array entries out of order");
+};
+
+
+template <typename ArrayType, const ArrayType& array, size_t Index = 0>
+constexpr bool ValidateArrayOrdering()
+{
+ if constexpr (Index < array.size())
+ {
+ using OperationType = decltype(array[0].op);
+ (void)ArrayMismatchError<Index, static_cast<OperationType>(Index), array[Index].op>{};
+ return ValidateArrayOrdering<ArrayType, array, Index + 1>();
+ }
+ 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<decltype(array), array>(), \
+ "Array entries out of order, see ArrayMismatchError for details")