summaryrefslogtreecommitdiff
path: root/highlevelilinstruction.cpp
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 /highlevelilinstruction.cpp
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.
Diffstat (limited to 'highlevelilinstruction.cpp')
-rw-r--r--highlevelilinstruction.cpp471
1 files changed, 252 insertions, 219 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;
}