#ifndef MRT_STACK_MAP_TABLE_H
#define MRT_STACK_MAP_TABLE_H
#include "StackMap/StackMapTypeDef.h"
#include "CangjieRuntime.h"
#include "Base/LogFile.h"
namespace MapleRuntime {
using VarValue = U32;
using BitLen = U32;
using VarPair = std::pair<VarValue, BitLen>;
using DerivedPtrPair = std::pair<U32, U32>;
class BitsManager {
public:
BitsManager() = default;
BitsManager(U8* ptr, U32 pos) : addr(ptr), bitPos(pos) {}
BitsManager(const BitsManager& other) : addr(other.addr), bitPos(other.bitPos) {}
BitsManager& operator=(const BitsManager& other)
{
if (this == &other) {
return *this;
}
addr = other.addr;
bitPos = other.bitPos;
return *this;
}
BitsManager(BitsManager&& other) : addr(other.addr), bitPos(other.bitPos)
{
other.addr = nullptr;
other.bitPos = 0;
}
BitsManager& operator=(BitsManager&& other)
{
if (this == &other) {
return *this;
}
addr = other.addr;
bitPos = other.bitPos;
other.addr = nullptr;
other.bitPos = 0;
return *this;
}
~BitsManager() { addr = nullptr; }
U32 GetBits(U32 bitLen) const
{
U32 bitsMask = static_cast<U32>((1ULL << bitLen) - 1);
return ((ConnectBytesToU64() >> bitPos) & bitsMask);
}
ATTR_NO_INLINE BitsManager GetNext(U32 bitsLen) const
{
U32 addrStep = bitsLen >> BITS_SHIFT_PER_BYTE;
constexpr U32 bitsMask = (1 << BITS_SHIFT_PER_BYTE) - 1;
U32 bitPosStep = bitsLen & bitsMask;
U8* nextAddr = addr + addrStep;
U32 nextBitPos = bitPos + bitPosStep;
if (nextBitPos >= BITS_NUM_PER_BYTE) {
++nextAddr;
nextBitPos -= BITS_NUM_PER_BYTE;
}
return BitsManager(nextAddr, nextBitPos);
}
private:
U64 ConnectBytesToU64() const
{
constexpr U32 len = sizeof(U32) / sizeof(U8) + 1;
U64 value = 0;
U32 shiftSteps = 0;
for (U32 i = 0; i < len; ++i, shiftSteps += BITS_NUM_PER_BYTE) {
value |= static_cast<U64>(addr[i]) << shiftSteps;
}
return value;
}
static constexpr U32 BITS_NUM_PER_BYTE = 8;
static constexpr U32 BITS_SHIFT_PER_BYTE = 3;
static constexpr U32 BITS_NUM_HALF_BYTE = BITS_NUM_PER_BYTE >> 1;
static constexpr U16 HALF_BYTE_MASK = (1 << BITS_NUM_HALF_BYTE) - 1;
U8* addr{ nullptr };
U32 bitPos{ 0 };
};
class VarInt {
public:
enum TagType : U8 {
MAX_VALID_VALUE = 11,
VAR_VALUE8 = 12,
VAR_VALUE16 = 13,
VAR_VALUE24 = 14,
VAR_VALUE32 = 15,
};
enum BitsLen : U32 {
TAG_LEN = 4,
FIRST_STEP_VAR_BITS = 8,
SECOND_STEP_VAR_BITS = 16,
THIRD_STEP_VAR_BITS = 24,
FORTH_STEP_VAR_BITS = 32,
};
VarInt() = delete;
VarInt(U8* ptr, U32 pos) : bits(ptr, pos) {}
explicit VarInt(const BitsManager& bitsManager) : bits(bitsManager) {}
explicit VarInt(BitsManager&& bitsManager) : bits(bitsManager) {}
~VarInt() = default;
ATTR_NO_INLINE VarPair GetValue() const
{
uint8_t tag = static_cast<uint8_t>(bits.GetBits(TAG_LEN));
if (tag <= MAX_VALID_VALUE) {
return std::make_pair(static_cast<VarValue>(tag), TAG_LEN);
}
if (tag == VAR_VALUE8) {
VarValue value = GetPayload(FIRST_STEP_VAR_BITS);
return std::make_pair(value, TAG_LEN + FIRST_STEP_VAR_BITS);
}
if (tag == VAR_VALUE16) {
VarValue value = GetPayload(SECOND_STEP_VAR_BITS);
return std::make_pair(value, TAG_LEN + SECOND_STEP_VAR_BITS);
}
if (tag == VAR_VALUE24) {
uint32_t value = GetPayload(THIRD_STEP_VAR_BITS);
return std::make_pair(value, TAG_LEN + THIRD_STEP_VAR_BITS);
}
VarValue value = GetPayload(FORTH_STEP_VAR_BITS);
return std::make_pair(value, TAG_LEN + FORTH_STEP_VAR_BITS);
}
private:
VarValue GetPayload(BitsLen bitsLen) const
{
BitsManager payload = bits.GetNext(TAG_LEN);
return payload.GetBits(bitsLen);
}
BitsManager bits;
};
class TableAPI {
public:
TableAPI() = default;
TableAPI(U8* tableAddrStart, U32 tableBitStart) : tableBits(tableAddrStart, tableBitStart) {}
explicit TableAPI(const BitsManager& bits) : tableBits(bits) {}
explicit TableAPI(BitsManager&& bits) : tableBits(bits) {}
virtual ~TableAPI() = default;
BitsManager GetNextTable() const { return nextTable; };
protected:
ATTR_NO_INLINE BitsManager ResolveHeader(U32 headerInfo[], U32 size)
{
BitsManager cur(tableBits);
for (U32 i = 0; i < size; ++i) {
VarInt varInt(cur);
VarPair headerPair = varInt.GetValue();
VarValue value = headerPair.first;
headerInfo[i] = value;
cur = cur.GetNext(headerPair.second);
}
return cur;
}
BitsManager tableBits;
U32 rowBitsLen{ 0 };
BitsManager data;
BitsManager nextTable;
};
struct PrologueRegisterClosure {
PrologueRegisterClosure() = default;
PrologueRegisterClosure(PrologueRegisterClosure&& other)
: calleeSaved(std::move(other.calleeSaved)), offset(std::move(other.offset)) {}
PrologueRegisterClosure& operator=(PrologueRegisterClosure&& other)
{
if (this == &other) {
return *this;
}
calleeSaved = std::move(other.calleeSaved);
offset = std::move(other.offset);
return *this;
}
enum class Type : U32 { CALLEE_REGISTER, OFFSET };
~PrologueRegisterClosure() = default;
void RecordCalleeSaved(RegSlotsMap& regSlotsMap, uintptr_t base) const
{
size_t size = calleeSaved.size();
for (size_t i = 0; i < size; ++i) {
regSlotsMap.Insert(
Register::ResolveCalleeSaved(calleeSaved[i]),
reinterpret_cast<SlotAddress>(static_cast<intptr_t>(base) + (static_cast<intptr_t>(offset[i] * COEF))));
}
}
#if defined(__APPLE__) && defined(__aarch64__)
constexpr static intptr_t COEF = -8;
#elif defined(__aarch64__)
constexpr static intptr_t COEF = 8;
#elif defined(__arm__)
constexpr static intptr_t COEF = -4;
#else
constexpr static intptr_t COEF = -8;
#endif
std::vector<U32> calleeSaved;
std::vector<U32> offset;
};
using PrologueVisitor = std::function<void(PrologueRegisterClosure::Type, U32)>;
class PrologueVarInt {
public:
PrologueVarInt(U8* ptr, U32 bitPos, const PrologueVisitor& visitor) : prologue(ptr, bitPos)
{
ResolvePrologue(visitor);
}
explicit PrologueVarInt(const BitsManager& bitsManager, const PrologueVisitor& visitor) : prologue(bitsManager)
{
ResolvePrologue(visitor);
}
~PrologueVarInt() = default;
BitsManager GetNextTable() const { return nextTable; }
private:
void ResolvePrologue(const PrologueVisitor& visitor)
{
VarInt regBits(prologue);
VarPair varPair = regBits.GetValue();
U32 bitMap = varPair.first;
U32 bitLen = varPair.second;
U32 size = 0;
for (U32 i = 0; bitMap != 0; ++i, bitMap >>= 1) {
constexpr U32 bitMask = 0x1;
if ((bitMap & bitMask) == 0) {
continue;
}
if (LIKELY(visitor != nullptr)) {
visitor(PrologueRegisterClosure::Type::CALLEE_REGISTER, i);
}
++size;
}
BitsManager offsetBitManager = prologue.GetNext(bitLen);
for (U32 i = 0; i < size; ++i) {
VarInt offsetVarInt(offsetBitManager);
VarPair offsetPair = offsetVarInt.GetValue();
if (LIKELY(visitor != nullptr)) {
visitor(PrologueRegisterClosure::Type::OFFSET, offsetPair.first);
}
offsetBitManager = offsetBitManager.GetNext(offsetPair.second);
}
nextTable = offsetBitManager;
}
BitsManager prologue;
BitsManager nextTable;
};
class RegTable : public TableAPI {
public:
RegTable() = default;
RegTable(U8* tableAddrStart, U32 tableBitStart) : TableAPI(tableAddrStart, tableBitStart) { Init(); }
explicit RegTable(const BitsManager& bits) : TableAPI(bits) { Init(); }
explicit RegTable(BitsManager&& bits) : TableAPI(bits) { Init(); }
~RegTable() = default;
U32 GetActiveRegBits(U32 row) const { return data.GetNext(row * rowBitsLen).GetBits(headerInfo[BITS_LEN]); }
private:
void Init()
{
data = ResolveHeader(headerInfo, HEADER_COL_NUM);
rowBitsLen = headerInfo[BITS_LEN];
nextTable = data.GetNext(rowBitsLen * headerInfo[RECORD_NUM]);
}
enum HeaderColTag {
RECORD_NUM = 0,
BITS_LEN,
HEADER_COL_NUM,
};
U32 headerInfo[HEADER_COL_NUM]{ 0 };
};
class SlotTable : public TableAPI {
public:
SlotTable() = default;
SlotTable(U8* tableAddrStart, U32 tableBitStart, U32 format) : TableAPI(tableAddrStart, tableBitStart),
slotFormat(format) { Init(); }
SlotTable(const BitsManager& bits, U32 format) : TableAPI(bits), slotFormat(format) { Init(); }
SlotTable(BitsManager&& bits, U32 format) : TableAPI(bits), slotFormat(format) { Init(); }
~SlotTable() = default;
SlotBias GetBaseOffset(U32 row) const
{
U32 unsignedValue = data.GetNext(row * rowBitsLen).GetBits(headerInfo[BASE_OFF_BITS_LEN]);
switch (headerInfo[BASE_OFF_BITS_LEN]) {
case SIGNED8:
return static_cast<SlotBias>(static_cast<I8>(unsignedValue));
case SIGNED16:
return static_cast<SlotBias>(static_cast<I16>(unsignedValue));
case SIGNED32:
return static_cast<SlotBias>(static_cast<I32>(unsignedValue));
default:
LOG(RTLOG_FATAL, "wrong length of base offset bits length");
return static_cast<SlotBias>(unsignedValue);
}
}
std::vector<SlotBits> GetSlotBitMap(U32 row) const
{
if (slotFormat != PURE_COMPRESSED_STACKMAP) {
return GetWAHSlotBitMap(row);
}
constexpr U32 regularSlotBitsLen = 32;
constexpr U32 regularShiftBits = 5;
constexpr U32 bitMask = (1 << regularShiftBits) - 1;
U32 bitMapLen = headerInfo[BIT_MAP_BITS_LEN];
U32 size = bitMapLen >> regularShiftBits;
U32 resident = bitMapLen & bitMask;
if (resident != 0) {
size++;
}
std::vector<SlotBits> buffer(size);
BitsManager bitMapBits = data.GetNext(row * rowBitsLen + headerInfo[BASE_OFF_BITS_LEN]);
for (U32 i = 0; i < size - 1; ++i, bitMapBits = bitMapBits.GetNext(regularSlotBitsLen)) {
buffer[i] = bitMapBits.GetBits(regularSlotBitsLen);
}
if (resident == 0) {
buffer[size - 1] = bitMapBits.GetBits(regularSlotBitsLen);
} else {
buffer[size - 1] = bitMapBits.GetBits(resident);
}
size_t validSize = size;
for (U32 i = size - 1; i != 0; i--) {
if (buffer[i] != 0) {
break;
}
validSize--;
}
buffer.resize(validSize);
return buffer;
}
U32 slotFormat;
private:
void Init()
{
data = ResolveHeader(headerInfo, HEADER_COL_NUM);
rowBitsLen = headerInfo[BASE_OFF_BITS_LEN] + headerInfo[BIT_MAP_BITS_LEN];
nextTable = data.GetNext(headerInfo[RECORD_NUM] * rowBitsLen);
}
std::vector<SlotBits> GetWAHSlotBitMap(U32 row) const
{
U32 remainLen = headerInfo[BIT_MAP_BITS_LEN];
BitsManager bitMapBits = data.GetNext(row * rowBitsLen + headerInfo[BASE_OFF_BITS_LEN]);
std::vector<SlotBits> result;
U32 isPureVal;
U32 isAllRef;
VarValue cnts;
constexpr U32 PureValWidth = 31;
constexpr U32 PureValMask = 1 << PureValWidth;
constexpr U32 CompressTagBitPos = 30;
while (remainLen != 0) {
isPureVal = bitMapBits.GetBits(1);
bitMapBits = bitMapBits.GetNext(1);
remainLen--;
if (isPureVal) {
U32 pureValBits = std::min(remainLen, PureValWidth);
result.push_back(bitMapBits.GetBits(pureValBits) | PureValMask);
bitMapBits = bitMapBits.GetNext(pureValBits);
remainLen -= pureValBits;
} else {
if (remainLen < VarInt::TAG_LEN + 1) {
break;
}
isAllRef = bitMapBits.GetBits(1);
bitMapBits = bitMapBits.GetNext(1);
remainLen--;
VarInt varInt(bitMapBits);
VarPair varIntPair = varInt.GetValue();
cnts = varIntPair.first;
bitMapBits = bitMapBits.GetNext(varIntPair.second);
remainLen -= varIntPair.second;
if (cnts == 0) {
break;
}
result.push_back(cnts |= (isAllRef << CompressTagBitPos));
}
}
return result;
}
enum HeaderColTag {
RECORD_NUM = 0,
BASE_OFF_BITS_LEN,
BIT_MAP_BITS_LEN,
HEADER_COL_NUM,
};
enum BaseOffsetType {
SIGNED8 = 8,
SIGNED16 = 16,
SIGNED32 = 32,
};
U32 headerInfo[HEADER_COL_NUM]{ 0 };
};
class LineNumTable : public TableAPI {
public:
LineNumTable() = default;
LineNumTable(U8* tableAddrStart, U32 tableBitStart) : TableAPI(tableAddrStart, tableBitStart) { Init(); }
explicit LineNumTable(const BitsManager& bits) : TableAPI(bits) { Init(); }
explicit LineNumTable(BitsManager&& bits) : TableAPI(bits) { Init(); }
~LineNumTable() = default;
U32 GetLineNumber(U32 row) const { return data.GetNext(row * rowBitsLen).GetBits(headerInfo[LINE_NUM_BITS_LEN]); }
private:
void Init()
{
data = ResolveHeader(headerInfo, HEADER_COL_NUM);
rowBitsLen = headerInfo[LINE_NUM_BITS_LEN];
nextTable = data.GetNext(rowBitsLen * headerInfo[RECORD_NUM]);
}
enum HeaderTag {
RECORD_NUM = 0,
LINE_NUM_BITS_LEN,
HEADER_COL_NUM,
};
U32 headerInfo[HEADER_COL_NUM]{ 0 };
};
struct IdxSet {
IdxSet() : regIdx(0), slotIdx(0), lineNumIdx(0), derivedPtrIdx(0), stackRegIdx(0), stackSlotIdx(0) {}
IdxSet(U32 reg, U32 slot, U32 lineNum, U32 derivePtr, U32 stackReg, U32 stackSlot)
: regIdx(reg), slotIdx(slot), lineNumIdx(lineNum), derivedPtrIdx(derivePtr),
stackRegIdx(stackReg), stackSlotIdx(stackSlot) {}
IdxSet(U32 reg, U32 slot, U32 lineNum, U32 derivePtr)
: regIdx(reg), slotIdx(slot), lineNumIdx(lineNum), derivedPtrIdx(derivePtr),
stackRegIdx(0), stackSlotIdx(0) {}
U32 regIdx;
U32 slotIdx;
U32 lineNumIdx;
U32 derivedPtrIdx;
U32 stackRegIdx;
U32 stackSlotIdx;
};
class StackMapTable : public TableAPI {
public:
StackMapTable(U8* tableAddrStart, U32 tableBitStart) : TableAPI(tableAddrStart, tableBitStart) { Init(); }
explicit StackMapTable(const BitsManager& bits) : TableAPI(bits) { Init(); }
explicit StackMapTable(BitsManager&& bits) : TableAPI(bits) { Init(); }
~StackMapTable() = default;
IdxSet GetIdxSet(Uptr startPC, Uptr framePC) const
{
U32 recordNum = headerInfo[RECORD_NUM];
if (recordNum == 0) {
return IdxSet();
}
U32 targetPCOff = static_cast<U32>(framePC - startPC);
U32 left = 0;
U32 right = recordNum - 1;
U32 leftPCOff = PCAt(left);
if (leftPCOff == targetPCOff) {
if (CangjieRuntime::stackGrowConfig == StackGrowConfig::STACK_GROW_ON) {
return IdxSet(RegIdxAt(left), SlotIdxAt(left), LineNumIdxAt(left),
DerivePtrIdxAt(left), StackRegIdxAt(left), StackSlotIdxAt(left));
} else {
return IdxSet(RegIdxAt(left), SlotIdxAt(left), LineNumIdxAt(left), DerivePtrIdxAt(left));
}
}
U32 rightPCOff = PCAt(right);
if (rightPCOff == targetPCOff) {
if (CangjieRuntime::stackGrowConfig == StackGrowConfig::STACK_GROW_ON) {
return IdxSet(RegIdxAt(right), SlotIdxAt(right), LineNumIdxAt(right),
DerivePtrIdxAt(right), StackRegIdxAt(right), StackSlotIdxAt(right));
} else {
return IdxSet(RegIdxAt(right), SlotIdxAt(right), LineNumIdxAt(right), DerivePtrIdxAt(right));
}
}
if (targetPCOff < leftPCOff || targetPCOff > rightPCOff) {
DLOG(ENUM, "stack map is empty in this frame");
return IdxSet();
}
while (left <= right) {
U32 mid = (left + right) >> 1;
U32 midPCOff = PCAt(mid);
if (midPCOff == targetPCOff) {
if (CangjieRuntime::stackGrowConfig == StackGrowConfig::STACK_GROW_ON) {
return IdxSet(RegIdxAt(mid), SlotIdxAt(mid), LineNumIdxAt(mid),
DerivePtrIdxAt(mid), StackRegIdxAt(mid), StackSlotIdxAt(mid));
} else {
return IdxSet(RegIdxAt(mid), SlotIdxAt(mid), LineNumIdxAt(mid), DerivePtrIdxAt(mid));
}
} else if (midPCOff < targetPCOff) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return IdxSet();
}
U32 GetRegBitsLen() const { return headerInfo[REG_BITS_LEN]; }
U32 GetSlotBitsLen() const { return headerInfo[SLOT_BITS_LEN]; }
private:
void Init()
{
if (CangjieRuntime::stackGrowConfig == StackGrowConfig::STACK_GROW_ON) {
data = ResolveHeader(headerInfo, HEADER_COL_NUM).GetNext(headerInfo[PADDING_BITS_LEN]);
rowBitsLen = PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN] +
headerInfo[LINE_NUM_BITS_LEN] + headerInfo[DERIVE_PTR_BITS_LEN] +
headerInfo[STACK_REG_BITS_LEN] + headerInfo[STACK_SLOT_BITS_LEN];
nextTable = data.GetNext(rowBitsLen * headerInfo[RECORD_NUM]);
} else {
data = ResolveHeader(headerInfo, HEADER_COL_NUM - STACK_ITEM_NUM).GetNext(headerInfo[PADDING_BITS_LEN -
STACK_ITEM_NUM]);
rowBitsLen = PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN] +
headerInfo[LINE_NUM_BITS_LEN] + headerInfo[DERIVE_PTR_BITS_LEN];
nextTable = data.GetNext(rowBitsLen * headerInfo[RECORD_NUM]);
}
}
U32 PCAt(U32 row) const
{
auto bitsManager = data.GetNext(row * rowBitsLen);
return bitsManager.GetBits(PC_OFF_BITS);
}
U32 RegIdxAt(U32 row) const
{
auto bitsManager = data.GetNext(row * rowBitsLen + PC_OFF_BITS);
return bitsManager.GetBits(headerInfo[REG_BITS_LEN]);
}
U32 SlotIdxAt(U32 row) const
{
auto bitsManager = data.GetNext(row * rowBitsLen + PC_OFF_BITS + headerInfo[REG_BITS_LEN]);
return bitsManager.GetBits(headerInfo[SLOT_BITS_LEN]);
}
U32 LineNumIdxAt(U32 row) const
{
U32 skipBitsLen = row * rowBitsLen + PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN];
auto bitsManager = data.GetNext(skipBitsLen);
return bitsManager.GetBits(headerInfo[LINE_NUM_BITS_LEN]);
}
U32 DerivePtrIdxAt(U32 row) const
{
U32 skipBitsLen = row * rowBitsLen + PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN] +
headerInfo[LINE_NUM_BITS_LEN];
auto bitsManager = data.GetNext(skipBitsLen);
return bitsManager.GetBits(headerInfo[DERIVE_PTR_BITS_LEN]);
}
U32 StackRegIdxAt(U32 row) const
{
U32 skipBitsLen = row * rowBitsLen + PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN] +
headerInfo[LINE_NUM_BITS_LEN] + headerInfo[DERIVE_PTR_BITS_LEN];
auto bitsManager = data.GetNext(skipBitsLen);
return bitsManager.GetBits(headerInfo[STACK_REG_BITS_LEN]);
}
U32 StackSlotIdxAt(U32 row) const
{
U32 skipBitsLen = row * rowBitsLen + PC_OFF_BITS + headerInfo[REG_BITS_LEN] + headerInfo[SLOT_BITS_LEN] +
headerInfo[LINE_NUM_BITS_LEN] + headerInfo[DERIVE_PTR_BITS_LEN] + headerInfo[STACK_REG_BITS_LEN];
auto bitsManager = data.GetNext(skipBitsLen);
return bitsManager.GetBits(headerInfo[STACK_SLOT_BITS_LEN]);
}
enum HeaderColTag : U32 {
RECORD_NUM = 0,
REG_BITS_LEN,
SLOT_BITS_LEN,
LINE_NUM_BITS_LEN,
DERIVE_PTR_BITS_LEN,
STACK_REG_BITS_LEN,
STACK_SLOT_BITS_LEN,
PADDING_BITS_LEN,
HEADER_COL_NUM,
};
static constexpr U32 STACK_ITEM_NUM = 2;
static constexpr U32 PC_OFF_BITS = 32;
U32 headerInfo[HEADER_COL_NUM]{ 0 };
};
class DerivedPtrTable : public TableAPI {
public:
DerivedPtrTable() = default;
explicit DerivedPtrTable(const BitsManager& bits, U32 regBits, U32 slotBits)
: TableAPI(bits), regBitsLen(regBits), slotBitsLen(slotBits) { Init(); }
explicit DerivedPtrTable(BitsManager&& bits, U32 regBits, U32 slotBits)
: TableAPI(bits), regBitsLen(regBits), slotBitsLen(slotBits) { Init(); }
~DerivedPtrTable() = default;
DerivedPtrPair GetDerivePair(U32 row) const
{
BitsManager rowBits = data.GetNext(row * rowBitsLen);
return std::make_pair(rowBits.GetBits(regBitsLen), rowBits.GetNext(regBitsLen).GetBits(slotBitsLen));
}
private:
void Init()
{
data = ResolveHeader(headerInfo, HEADER_COL_NUM);
rowBitsLen = regBitsLen + slotBitsLen;
}
enum HeaderTag {
RECORD_NUM = 0,
HEADER_COL_NUM,
};
U32 headerInfo[HEADER_COL_NUM];
U32 regBitsLen = 0;
U32 slotBitsLen = 0;
};
}
#endif