RzIL: Hash Pure variable names to make them more suitable as hash table keys. (#5971)

* Pre-compute DJB2 hash of VAR name for internal hash map key usage.

* IL VARS hash: Hash variable name.

* Add tests
This commit is contained in:
Rot127 2026-02-27 11:51:35 +00:00 committed by GitHub
parent a65be1e6cd
commit ec02889e9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 11 additions and 0 deletions

View file

@ -66,6 +66,7 @@ RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *v, RzILVarKind
rz_return_val_if_fail(v, NULL);
RzILOpPure *ret;
rz_il_op_new_2(Pure, RZ_IL_OP_VAR, RzILOpArgsVar, var, v, kind);
ret->op.var.hash = rz_str_djb2_hash(v);
return ret;
}
@ -76,6 +77,7 @@ RZ_API RZ_OWN RzILOpPure *rz_il_op_new_let(RZ_NONNULL const char *name, RZ_NONNU
rz_return_val_if_fail(name && exp && body, NULL);
RzILOpPure *ret;
rz_il_op_new_3(Pure, RZ_IL_OP_LET, RzILOpArgsLet, let, name, exp, body);
ret->op.let.hash = rz_str_djb2_hash(name);
return ret;
}
@ -578,6 +580,7 @@ RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *v, bool is_l
rz_return_val_if_fail(v && x, NULL);
RzILOpEffect *ret;
rz_il_op_new_3(Effect, RZ_IL_OP_SET, RzILOpArgsSet, set, v, is_local, x);
ret->op.set.hash = rz_str_djb2_hash(v);
return ret;
}
@ -1090,6 +1093,7 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) {
switch (op->code) {
case RZ_IL_OP_VAR:
r->op.var.v = op->op.var.v;
r->op.var.hash = op->op.var.hash;
r->op.var.kind = op->op.var.kind;
break;
case RZ_IL_OP_ITE:
@ -1097,6 +1101,7 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) {
break;
case RZ_IL_OP_LET:
r->op.let.name = op->op.let.name;
r->op.let.hash = op->op.let.hash;
DUP_OP2(let, exp, body);
break;
case RZ_IL_OP_B0:

View file

@ -167,6 +167,7 @@ typedef struct rz_il_op_args_shift_t RzILOpArgsShiftRight;
*/
typedef struct rz_il_op_args_set_t {
const char *v; ///< name of variable, const one
ut64 hash; ///< DJB2 hash of variable name
bool is_local; ///< whether a global variable should be set or a local optionally created and set
RzILOpPure *x; ///< value to set the variable to
} RzILOpArgsSet;
@ -178,6 +179,7 @@ typedef struct rz_il_op_args_set_t {
*/
typedef struct rz_il_op_args_let_t {
const char *name; ///< name of variable
ut64 hash; ///< DJB2 hash of variable name
RzILOpPure *exp; ///< value/expression to bind the variable to
RzILOpPure *body; ///< body in which the variable will be bound and that produces the result
} RzILOpArgsLet;
@ -260,6 +262,7 @@ typedef struct rz_il_op_args_ite_t {
*/
typedef struct rz_il_op_args_var_t {
const char *v; ///< name of variable, const one
ut64 hash; ///< The DJB2 hash of the name.
RzILVarKind kind; ///< set of variables to pick from
} RzILOpArgsVar;

View file

@ -103,6 +103,7 @@ static bool test_il_validate_pure_let() {
RzILSortPure sort;
RzILValidateReport report;
bool val = rz_il_validate_pure(op, ctx, &sort, &report);
mu_assert_eq(op->op.let.hash, rz_str_djb2_hash("x"), "Hash mismatch");
mu_assert_true(val, "valid");
mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64)), "sort");
mu_assert_null(report, "no report");
@ -179,6 +180,7 @@ static bool test_il_validate_pure_var() {
mu_assert_true(val, "valid");
mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(42)), "sort");
mu_assert_null(report, "no report");
mu_assert_eq(op->op.var.hash, rz_str_djb2_hash("y"), "Hash mismatch");
rz_il_op_pure_free(op);
RzILOpEffect *eop = rz_il_op_new_seq(
@ -195,6 +197,7 @@ static bool test_il_validate_pure_var() {
val = rz_il_validate_pure(op, ctx, &sort, &report);
mu_assert_false(val, "invalid");
mu_assert_streq_free(report, "Global variable \"x\" referenced by var op does not exist.", "report");
mu_assert_eq(op->op.var.hash, rz_str_djb2_hash("x"), "Hash mismatch");
rz_il_op_pure_free(op);
op = rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL);