summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Rowe <mark@vector35.com>2025-07-16 18:42:37 -0700
committerMark Rowe <mark@vector35.com>2025-12-11 21:09:38 -0800
commit62ded0de7b820f6e25be31254158401ce31a1c87 (patch)
tree83ff5d27bc01af2cec331eaf148de80914357420
parent290bbcf333679ffa057d57d1b540608e3bec8ada (diff)
Use constexpr arrays for metadata about IL instruction operands
This avoids constructing two unordered maps and numerous vectors for each IL level at library load time for each plug-in that uses the C++ API. Additionally, the arrays allow for more efficient look-ups.
-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")