mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
remove exceptionMap from LimExNFA
This commit is contained in:
parent
6331da4e29
commit
702f256b39
@ -1172,12 +1172,13 @@ u32 getReportListIndex(const flat_set<ReportID> &reports,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void buildExceptionMap(const build_info &args,
|
u32 buildExceptionMap(const build_info &args,
|
||||||
const ue2::unordered_set<NFAEdge> &exceptional,
|
const ue2::unordered_set<NFAEdge> &exceptional,
|
||||||
map<ExceptionProto, vector<u32> > &exceptionMap,
|
map<ExceptionProto, vector<u32> > &exceptionMap,
|
||||||
vector<ReportID> &exceptionReports) {
|
vector<ReportID> &exceptionReports) {
|
||||||
const NGHolder &h = args.h;
|
const NGHolder &h = args.h;
|
||||||
const u32 num_states = args.num_states;
|
const u32 num_states = args.num_states;
|
||||||
|
u32 exceptionCount = 0;
|
||||||
|
|
||||||
ue2::unordered_map<NFAVertex, u32> pos_trigger;
|
ue2::unordered_map<NFAVertex, u32> pos_trigger;
|
||||||
ue2::unordered_map<NFAVertex, u32> tug_trigger;
|
ue2::unordered_map<NFAVertex, u32> tug_trigger;
|
||||||
@ -1307,10 +1308,13 @@ void buildExceptionMap(const build_info &args,
|
|||||||
assert(e.succ_states.size() == num_states);
|
assert(e.succ_states.size() == num_states);
|
||||||
assert(e.squash_states.size() == num_states);
|
assert(e.squash_states.size() == num_states);
|
||||||
exceptionMap[e].push_back(i);
|
exceptionMap[e].push_back(i);
|
||||||
|
exceptionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_PRINTF("%zu unique exceptions found.\n", exceptionMap.size());
|
DEBUG_PRINTF("%u exceptions found (%zu unique)\n", exceptionCount,
|
||||||
|
exceptionMap.size());
|
||||||
|
return exceptionCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -1642,19 +1646,25 @@ struct Factory {
|
|||||||
implNFA_t *limex, const u32 exceptionsOffset) {
|
implNFA_t *limex, const u32 exceptionsOffset) {
|
||||||
DEBUG_PRINTF("exceptionsOffset=%u\n", exceptionsOffset);
|
DEBUG_PRINTF("exceptionsOffset=%u\n", exceptionsOffset);
|
||||||
|
|
||||||
// to make testing easier, we pre-set the exceptionMap to all invalid
|
|
||||||
// values
|
|
||||||
memset(limex->exceptionMap, 0xff, sizeof(limex->exceptionMap));
|
|
||||||
|
|
||||||
exception_t *etable = (exception_t *)((char *)limex + exceptionsOffset);
|
exception_t *etable = (exception_t *)((char *)limex + exceptionsOffset);
|
||||||
assert(ISALIGNED(etable));
|
assert(ISALIGNED(etable));
|
||||||
|
|
||||||
u32 ecount = 0;
|
map<u32, ExceptionProto> exception_by_state;
|
||||||
for (const auto &m : exceptionMap) {
|
for (const auto &m : exceptionMap) {
|
||||||
const ExceptionProto &proto = m.first;
|
const ExceptionProto &proto = m.first;
|
||||||
const vector<u32> &states = m.second;
|
const vector<u32> &states = m.second;
|
||||||
DEBUG_PRINTF("exception %u, triggered by %zu states.\n", ecount,
|
for (u32 i : states) {
|
||||||
states.size());
|
assert(!contains(exception_by_state, i));
|
||||||
|
exception_by_state.emplace(i, proto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ecount = 0;
|
||||||
|
for (const auto &m : exception_by_state) {
|
||||||
|
const ExceptionProto &proto = m.second;
|
||||||
|
u32 state_id = m.first;
|
||||||
|
DEBUG_PRINTF("exception %u, triggered by state %u\n", ecount,
|
||||||
|
state_id);
|
||||||
|
|
||||||
// Write the exception entry.
|
// Write the exception entry.
|
||||||
exception_t &e = etable[ecount];
|
exception_t &e = etable[ecount];
|
||||||
@ -1668,13 +1678,10 @@ struct Factory {
|
|||||||
: repeatOffsets[proto.repeat_index];
|
: repeatOffsets[proto.repeat_index];
|
||||||
e.repeatOffset = repeat_offset;
|
e.repeatOffset = repeat_offset;
|
||||||
|
|
||||||
// for each state that can switch it on
|
// for the state that can switch it on
|
||||||
for (auto state_id : states) {
|
// set this bit in the exception mask
|
||||||
// set this bit in the exception mask
|
maskSetBit(limex->exceptionMask, state_id);
|
||||||
maskSetBit(limex->exceptionMask, state_id);
|
|
||||||
// set this index in the exception map
|
|
||||||
limex->exceptionMap[state_id] = ecount;
|
|
||||||
}
|
|
||||||
ecount++;
|
ecount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1882,12 +1889,10 @@ struct Factory {
|
|||||||
|
|
||||||
map<ExceptionProto, vector<u32> > exceptionMap;
|
map<ExceptionProto, vector<u32> > exceptionMap;
|
||||||
vector<ReportID> exceptionReports;
|
vector<ReportID> exceptionReports;
|
||||||
buildExceptionMap(args, exceptional, exceptionMap, exceptionReports);
|
u32 exceptionCount = buildExceptionMap(args, exceptional, exceptionMap,
|
||||||
|
exceptionReports);
|
||||||
|
|
||||||
if (exceptionMap.size() > ~0U) {
|
assert(exceptionCount <= args.num_states);
|
||||||
DEBUG_PRINTF("too many exceptions!\n");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build reach table and character mapping.
|
// Build reach table and character mapping.
|
||||||
vector<NFAStateSet> reach;
|
vector<NFAStateSet> reach;
|
||||||
@ -1942,7 +1947,7 @@ struct Factory {
|
|||||||
|
|
||||||
offset = ROUNDUP_CL(offset);
|
offset = ROUNDUP_CL(offset);
|
||||||
const u32 exceptionsOffset = offset;
|
const u32 exceptionsOffset = offset;
|
||||||
offset += sizeof(exception_t) * exceptionMap.size();
|
offset += sizeof(exception_t) * exceptionCount;
|
||||||
|
|
||||||
const u32 exceptionReportsOffset = offset;
|
const u32 exceptionReportsOffset = offset;
|
||||||
offset += sizeof(ReportID) * exceptionReports.size();
|
offset += sizeof(ReportID) * exceptionReports.size();
|
||||||
|
@ -80,6 +80,21 @@ void dumpMask(FILE *f, const char *name, const u8 *mask, u32 mask_bits) {
|
|||||||
fprintf(f, "MSK %-20s %s\n", name, dumpMask(mask, mask_bits).c_str());
|
fprintf(f, "MSK %-20s %s\n", name, dumpMask(mask, mask_bits).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename mask_t>
|
||||||
|
static
|
||||||
|
u32 rank_in_mask(mask_t mask, u32 bit) {
|
||||||
|
u32 chunks[sizeof(mask)/sizeof(u32)];
|
||||||
|
memcpy(chunks, &mask, sizeof(mask));
|
||||||
|
u32 base_rank = 0;
|
||||||
|
for (u32 i = 0; i < bit / 32; i++) {
|
||||||
|
base_rank += popcount32(chunks[i]);
|
||||||
|
}
|
||||||
|
u32 chunk = chunks[bit / 32];
|
||||||
|
u32 local_bit = bit % 32;
|
||||||
|
assert(chunk & (1U << local_bit));
|
||||||
|
return base_rank + popcount32(chunk & ((1U << local_bit) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename limex_type>
|
template <typename limex_type>
|
||||||
static
|
static
|
||||||
void dumpRepeats(const limex_type *limex, u32 model_size, FILE *f) {
|
void dumpRepeats(const limex_type *limex, u32 model_size, FILE *f) {
|
||||||
@ -338,7 +353,7 @@ struct limex_labeller : public nfa_labeller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ex_index = limex->exceptionMap[state];
|
u32 ex_index = rank_in_mask(limex->exceptionMask, state);
|
||||||
const typename limex_traits<limex_type>::exception_type *e
|
const typename limex_traits<limex_type>::exception_type *e
|
||||||
= &exceptions[ex_index];
|
= &exceptions[ex_index];
|
||||||
|
|
||||||
@ -409,7 +424,7 @@ void dumpExDotInfo(const limex_type *limex, u32 state, FILE *f) {
|
|||||||
const typename limex_traits<limex_type>::exception_type *exceptions
|
const typename limex_traits<limex_type>::exception_type *exceptions
|
||||||
= getExceptionTable(limex);
|
= getExceptionTable(limex);
|
||||||
|
|
||||||
u32 ex_index = limex->exceptionMap[state];
|
u32 ex_index = rank_in_mask(limex->exceptionMask, state);
|
||||||
const typename limex_traits<limex_type>::exception_type *e
|
const typename limex_traits<limex_type>::exception_type *e
|
||||||
= &exceptions[ex_index];
|
= &exceptions[ex_index];
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Intel Corporation
|
* Copyright (c) 2015-2016, Intel Corporation
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -79,9 +79,13 @@
|
|||||||
#ifdef ARCH_64_BIT
|
#ifdef ARCH_64_BIT
|
||||||
#define CHUNK_T u64a
|
#define CHUNK_T u64a
|
||||||
#define FIND_AND_CLEAR_FN findAndClearLSB_64
|
#define FIND_AND_CLEAR_FN findAndClearLSB_64
|
||||||
|
#define POPCOUNT_FN popcount64
|
||||||
|
#define RANK_IN_MASK_FN rank_in_mask64
|
||||||
#else
|
#else
|
||||||
#define CHUNK_T u32
|
#define CHUNK_T u32
|
||||||
#define FIND_AND_CLEAR_FN findAndClearLSB_32
|
#define FIND_AND_CLEAR_FN findAndClearLSB_32
|
||||||
|
#define POPCOUNT_FN popcount32
|
||||||
|
#define RANK_IN_MASK_FN rank_in_mask32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** \brief Process a single exception. Returns 1 if exception handling should
|
/** \brief Process a single exception. Returns 1 if exception handling should
|
||||||
@ -206,13 +210,13 @@ int RUN_EXCEPTION_FN(const EXCEPTION_T *e, STATE_ARG,
|
|||||||
|
|
||||||
#ifndef RUN_EXCEPTION_FN_ONLY
|
#ifndef RUN_EXCEPTION_FN_ONLY
|
||||||
|
|
||||||
/** \brief Process all of the exceptions associated with the states in the \a estate. */
|
/** \brief Process all of the exceptions associated with the states in the \a
|
||||||
|
* estate. */
|
||||||
static really_inline
|
static really_inline
|
||||||
int PE_FN(STATE_ARG, ESTATE_ARG, u32 diffmask, STATE_T *succ,
|
int PE_FN(STATE_ARG, ESTATE_ARG, u32 diffmask, STATE_T *succ,
|
||||||
const struct IMPL_NFA_T *limex,
|
const struct IMPL_NFA_T *limex, const EXCEPTION_T *exceptions,
|
||||||
const u32 *exceptionMap, const EXCEPTION_T *exceptions,
|
const ReportID *exReports, u64a offset, struct CONTEXT_T *ctx,
|
||||||
const ReportID *exReports,
|
char in_rev, char flags) {
|
||||||
u64a offset, struct CONTEXT_T *ctx, char in_rev, char flags) {
|
|
||||||
assert(diffmask > 0); // guaranteed by caller macro
|
assert(diffmask > 0); // guaranteed by caller macro
|
||||||
|
|
||||||
if (EQ_STATE(estate, LOAD_STATE(&ctx->cached_estate))) {
|
if (EQ_STATE(estate, LOAD_STATE(&ctx->cached_estate))) {
|
||||||
@ -237,15 +241,23 @@ int PE_FN(STATE_ARG, ESTATE_ARG, u32 diffmask, STATE_T *succ,
|
|||||||
|
|
||||||
// A copy of the estate as an array of GPR-sized chunks.
|
// A copy of the estate as an array of GPR-sized chunks.
|
||||||
CHUNK_T chunks[sizeof(STATE_T) / sizeof(CHUNK_T)];
|
CHUNK_T chunks[sizeof(STATE_T) / sizeof(CHUNK_T)];
|
||||||
|
CHUNK_T emask_chunks[sizeof(STATE_T) / sizeof(CHUNK_T)];
|
||||||
#ifdef ESTATE_ON_STACK
|
#ifdef ESTATE_ON_STACK
|
||||||
memcpy(chunks, &estate, sizeof(STATE_T));
|
memcpy(chunks, &estate, sizeof(STATE_T));
|
||||||
#else
|
#else
|
||||||
memcpy(chunks, estatep, sizeof(STATE_T));
|
memcpy(chunks, estatep, sizeof(STATE_T));
|
||||||
#endif
|
#endif
|
||||||
|
memcpy(emask_chunks, &limex->exceptionMask, sizeof(STATE_T));
|
||||||
|
|
||||||
struct proto_cache new_cache = {0, NULL};
|
struct proto_cache new_cache = {0, NULL};
|
||||||
enum CacheResult cacheable = CACHE_RESULT;
|
enum CacheResult cacheable = CACHE_RESULT;
|
||||||
|
|
||||||
|
u32 base_index[sizeof(STATE_T) / sizeof(CHUNK_T)];
|
||||||
|
base_index[0] = 0;
|
||||||
|
for (u32 i = 0; i < ARRAY_LENGTH(base_index) - 1; i++) {
|
||||||
|
base_index[i + 1] = base_index[i] + POPCOUNT_FN(emask_chunks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
u32 t = findAndClearLSB_32(&diffmask);
|
u32 t = findAndClearLSB_32(&diffmask);
|
||||||
#ifdef ARCH_64_BIT
|
#ifdef ARCH_64_BIT
|
||||||
@ -254,10 +266,10 @@ int PE_FN(STATE_ARG, ESTATE_ARG, u32 diffmask, STATE_T *succ,
|
|||||||
assert(t < ARRAY_LENGTH(chunks));
|
assert(t < ARRAY_LENGTH(chunks));
|
||||||
CHUNK_T word = chunks[t];
|
CHUNK_T word = chunks[t];
|
||||||
assert(word != 0);
|
assert(word != 0);
|
||||||
u32 base = t * sizeof(CHUNK_T) * 8;
|
|
||||||
do {
|
do {
|
||||||
u32 bit = FIND_AND_CLEAR_FN(&word) + base;
|
u32 bit = FIND_AND_CLEAR_FN(&word);
|
||||||
u32 idx = exceptionMap[bit];
|
u32 local_index = RANK_IN_MASK_FN(emask_chunks[t], bit);
|
||||||
|
u32 idx = local_index + base_index[t];
|
||||||
const EXCEPTION_T *e = &exceptions[idx];
|
const EXCEPTION_T *e = &exceptions[idx];
|
||||||
|
|
||||||
if (!RUN_EXCEPTION_FN(e, STATE_ARG_NAME, succ,
|
if (!RUN_EXCEPTION_FN(e, STATE_ARG_NAME, succ,
|
||||||
|
@ -135,7 +135,6 @@ struct LimExNFA##size { \
|
|||||||
u32 exReportOffset; /* rel. to start of LimExNFA */ \
|
u32 exReportOffset; /* rel. to start of LimExNFA */ \
|
||||||
u32 repeatCount; \
|
u32 repeatCount; \
|
||||||
u32 repeatOffset; \
|
u32 repeatOffset; \
|
||||||
u32 exceptionMap[size]; \
|
|
||||||
u32 squashOffset; /* rel. to start of LimExNFA; for accept squashing */ \
|
u32 squashOffset; /* rel. to start of LimExNFA; for accept squashing */ \
|
||||||
u32 squashCount; \
|
u32 squashCount; \
|
||||||
u32 topCount; \
|
u32 topCount; \
|
||||||
|
@ -74,7 +74,6 @@
|
|||||||
static really_inline
|
static really_inline
|
||||||
int processExceptional32(u32 s, u32 estate, UNUSED u32 diffmask, u32 *succ,
|
int processExceptional32(u32 s, u32 estate, UNUSED u32 diffmask, u32 *succ,
|
||||||
const struct LimExNFA32 *limex,
|
const struct LimExNFA32 *limex,
|
||||||
const u32 *exceptionMap,
|
|
||||||
const struct NFAException32 *exceptions,
|
const struct NFAException32 *exceptions,
|
||||||
const ReportID *exReports, u64a offset,
|
const ReportID *exReports, u64a offset,
|
||||||
struct NFAContext32 *ctx, char in_rev, char flags) {
|
struct NFAContext32 *ctx, char in_rev, char flags) {
|
||||||
@ -104,7 +103,7 @@ int processExceptional32(u32 s, u32 estate, UNUSED u32 diffmask, u32 *succ,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
u32 bit = findAndClearLSB_32(&estate);
|
u32 bit = findAndClearLSB_32(&estate);
|
||||||
u32 idx = exceptionMap[bit];
|
u32 idx = rank_in_mask32(limex->exceptionMask, bit);
|
||||||
const struct NFAException32 *e = &exceptions[idx];
|
const struct NFAException32 *e = &exceptions[idx];
|
||||||
if (!runException32(e, s, succ, &local_succ, limex, exReports, offset,
|
if (!runException32(e, s, succ, &local_succ, limex, exReports, offset,
|
||||||
ctx, &new_cache, &cacheable, in_rev, flags)) {
|
ctx, &new_cache, &cacheable, in_rev, flags)) {
|
||||||
|
@ -105,8 +105,8 @@
|
|||||||
// continue, 1 if an accept was fired and the user instructed us to halt.
|
// continue, 1 if an accept was fired and the user instructed us to halt.
|
||||||
static really_inline
|
static really_inline
|
||||||
char RUN_EXCEPTIONS_FN(const IMPL_NFA_T *limex, const EXCEPTION_T *exceptions,
|
char RUN_EXCEPTIONS_FN(const IMPL_NFA_T *limex, const EXCEPTION_T *exceptions,
|
||||||
const ReportID *exReports, const u32 *exceptionMap,
|
const ReportID *exReports, STATE_T s,
|
||||||
STATE_T s, const STATE_T emask, size_t i, u64a offset,
|
const STATE_T emask, size_t i, u64a offset,
|
||||||
STATE_T *succ, u64a *final_loc, struct CONTEXT_T *ctx,
|
STATE_T *succ, u64a *final_loc, struct CONTEXT_T *ctx,
|
||||||
const char flags, const char in_rev,
|
const char flags, const char in_rev,
|
||||||
const char first_match) {
|
const char first_match) {
|
||||||
@ -133,8 +133,8 @@ char RUN_EXCEPTIONS_FN(const IMPL_NFA_T *limex, const EXCEPTION_T *exceptions,
|
|||||||
char localflags = (!i && !in_rev) ? NO_OUTPUT | FIRST_BYTE : flags;
|
char localflags = (!i && !in_rev) ? NO_OUTPUT | FIRST_BYTE : flags;
|
||||||
|
|
||||||
int rv = JOIN(processExceptional, SIZE)(
|
int rv = JOIN(processExceptional, SIZE)(
|
||||||
pass_state, pass_estate, diffmask, succ, limex, exceptionMap,
|
pass_state, pass_estate, diffmask, succ, limex, exceptions, exReports,
|
||||||
exceptions, exReports, callback_offset, ctx, in_rev, localflags);
|
callback_offset, ctx, in_rev, localflags);
|
||||||
if (rv == PE_RV_HALT) {
|
if (rv == PE_RV_HALT) {
|
||||||
return 1; // Halt matching.
|
return 1; // Halt matching.
|
||||||
}
|
}
|
||||||
@ -176,7 +176,6 @@ char STREAM_FN(const IMPL_NFA_T *limex, const u8 *input, size_t length,
|
|||||||
(const union AccelAux *)((const char *)limex + limex->accelAuxOffset);
|
(const union AccelAux *)((const char *)limex + limex->accelAuxOffset);
|
||||||
const EXCEPTION_T *exceptions = getExceptionTable(EXCEPTION_T, limex);
|
const EXCEPTION_T *exceptions = getExceptionTable(EXCEPTION_T, limex);
|
||||||
const ReportID *exReports = getExReports(limex);
|
const ReportID *exReports = getExReports(limex);
|
||||||
const u32 *exceptionMap = limex->exceptionMap;
|
|
||||||
STATE_T s = LOAD_STATE(&ctx->s);
|
STATE_T s = LOAD_STATE(&ctx->s);
|
||||||
|
|
||||||
/* assert(ISALIGNED_16(exceptions)); */
|
/* assert(ISALIGNED_16(exceptions)); */
|
||||||
@ -204,9 +203,9 @@ without_accel:
|
|||||||
STATE_T succ;
|
STATE_T succ;
|
||||||
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
||||||
|
|
||||||
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, exceptionMap, s,
|
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, s, EXCEPTION_MASK,
|
||||||
EXCEPTION_MASK, i, offset, &succ, final_loc, ctx,
|
i, offset, &succ, final_loc, ctx, flags, 0,
|
||||||
flags, 0, first_match)) {
|
first_match)) {
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,9 +254,9 @@ with_accel:
|
|||||||
STATE_T succ;
|
STATE_T succ;
|
||||||
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
||||||
|
|
||||||
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, exceptionMap, s,
|
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, s, EXCEPTION_MASK,
|
||||||
EXCEPTION_MASK, i, offset, &succ, final_loc, ctx,
|
i, offset, &succ, final_loc, ctx, flags, 0,
|
||||||
flags, 0, first_match)) {
|
first_match)) {
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +300,6 @@ char REV_STREAM_FN(const IMPL_NFA_T *limex, const u8 *input, size_t length,
|
|||||||
#endif
|
#endif
|
||||||
const EXCEPTION_T *exceptions = getExceptionTable(EXCEPTION_T, limex);
|
const EXCEPTION_T *exceptions = getExceptionTable(EXCEPTION_T, limex);
|
||||||
const ReportID *exReports = getExReports(limex);
|
const ReportID *exReports = getExReports(limex);
|
||||||
const u32 *exceptionMap = limex->exceptionMap;
|
|
||||||
STATE_T s = LOAD_STATE(&ctx->s);
|
STATE_T s = LOAD_STATE(&ctx->s);
|
||||||
|
|
||||||
/* assert(ISALIGNED_16(exceptions)); */
|
/* assert(ISALIGNED_16(exceptions)); */
|
||||||
@ -321,7 +319,7 @@ char REV_STREAM_FN(const IMPL_NFA_T *limex, const u8 *input, size_t length,
|
|||||||
STATE_T succ;
|
STATE_T succ;
|
||||||
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
NFA_EXEC_GET_LIM_SUCC(STATE_T);
|
||||||
|
|
||||||
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, exceptionMap, s,
|
if (RUN_EXCEPTIONS_FN(limex, exceptions, exReports, s,
|
||||||
EXCEPTION_MASK, i, offset, &succ, final_loc, ctx,
|
EXCEPTION_MASK, i, offset, &succ, final_loc, ctx,
|
||||||
flags, 1, 0)) {
|
flags, 1, 0)) {
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
|
@ -454,4 +454,20 @@ void bf64_unset(u64a *bitfield, u32 i) {
|
|||||||
*bitfield &= ~(1ULL << i);
|
*bitfield &= ~(1ULL << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static really_inline
|
||||||
|
u32 rank_in_mask32(u32 mask, u32 bit) {
|
||||||
|
assert(bit < sizeof(u32) * 8);
|
||||||
|
assert(mask & (u32)(1U << bit));
|
||||||
|
mask &= (u32)(1U << bit) - 1;
|
||||||
|
return popcount32(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static really_inline
|
||||||
|
u32 rank_in_mask64(u64a mask, u32 bit) {
|
||||||
|
assert(bit < sizeof(u64a) * 8);
|
||||||
|
assert(mask & (u64a)(1ULL << bit));
|
||||||
|
mask &= (u64a)(1ULL << bit) - 1;
|
||||||
|
return popcount64(mask);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BITUTILS_H
|
#endif // BITUTILS_H
|
||||||
|
@ -412,3 +412,27 @@ TEST(BitUtils, bf_it_1) {
|
|||||||
ASSERT_EQ(~0U, bf64_iterate(1ULL << 63, 63));
|
ASSERT_EQ(~0U, bf64_iterate(1ULL << 63, 63));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BitUtils, rank_in_mask32) {
|
||||||
|
for (u32 i = 0; i < 32; i++) {
|
||||||
|
ASSERT_EQ(i, rank_in_mask32(0xffffffff, i));
|
||||||
|
ASSERT_EQ(0, rank_in_mask32(1U << i, i));
|
||||||
|
}
|
||||||
|
ASSERT_EQ(0, rank_in_mask32(0xf0f0f0f0, 4));
|
||||||
|
ASSERT_EQ(1, rank_in_mask32(0xf0f0f0f0, 5));
|
||||||
|
ASSERT_EQ(3, rank_in_mask32(0xf0f0f0f0, 7));
|
||||||
|
ASSERT_EQ(7, rank_in_mask32(0xf0f0f0f0, 15));
|
||||||
|
ASSERT_EQ(15, rank_in_mask32(0xf0f0f0f0, 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BitUtils, rank_in_mask64) {
|
||||||
|
for (u32 i = 0; i < 64; i++) {
|
||||||
|
ASSERT_EQ(i, rank_in_mask64(0xffffffffffffffffULL, i));
|
||||||
|
ASSERT_EQ(0, rank_in_mask64(1ULL << i, i));
|
||||||
|
}
|
||||||
|
ASSERT_EQ(0, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 4));
|
||||||
|
ASSERT_EQ(1, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 5));
|
||||||
|
ASSERT_EQ(3, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 7));
|
||||||
|
ASSERT_EQ(7, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 15));
|
||||||
|
ASSERT_EQ(15, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 31));
|
||||||
|
ASSERT_EQ(31, rank_in_mask64(0xf0f0f0f0f0f0f0f0ULL, 63));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user