APInt(unsigned numBits, uint64_t val, bool isSigned = false) 中的参数 bool 是做什么用的?
what is the parameter bool in APInt(unsigned numBits, uint64_t val, bool isSigned = false) used for?
我很好奇第三个参数,来自 LLVM llvm/ADT/APInt.h
header 的 APInt(unsigned numBits, uint64_t val, bool isSigned = false)
中的布尔值 isSigned
。
无论我将其设置为什么,getActiveBits()
或 getMinSignedBits()
等函数的结果根本不会改变。
此外,如果我想获得 signed/unsigned 值,我会使用 getSExtValue()
或 getZExtValue()
。
isSigned
的价值对他们来说也不重要。
那么 isSigned
什么时候重要?
根据 docs 判断 val
是有符号还是无符号。
If isSigned is true then val is treated as if it were a signed value (i.e. as an int64_t) and the appropriate sign extension to the bit width will be done. Otherwise, no sign extension occurs (high order bits beyond the range of val are zero filled).
TL;DR: isSigned
仅对 numBits > 64
.
重要
sizeof(val)
只有64位。想象一下,您想将带符号的值存储在具有 size > 64 bits
.
的整数中
如果值为负数,所有高位必须设置为1
,因为负值通常存储为two's complement.
如果值为正数,所有高位必须设置为0
例子
假设您要以 128 位存储 -1。
持有-1的uint64_t val
的二进制表示是
1111111111111111111111111111111111111111111111111111111111111111
这里只有64位,所以还有64位需要补齐。如果没有 isSigned
值,就无法知道这些位是否应该是 ones,从而导致 -1 或 zeros,导致 18446744073709551615.
详细解释
一看 source code 就会发现,isSigned
仅在某些情况下使用:
APInt(unsigned numBits, uint64_t val, bool isSigned = false)
: BitWidth(numBits) {
assert(BitWidth && "bitwidth too small");
if (isSingleWord()) {
U.VAL = val;
clearUnusedBits();
} else {
initSlowCase(val, isSigned);
}
}
根据its function header、isSingleWord
returns true if the number of bits <= 64, false otherwise.
因此行
if (isSingleWord()) {
检查值的存储是否占用比 val
本身更多的内存。
如果 numBits
大于 64,则调用 APInt::initSlowCase
:
void APInt::initSlowCase(uint64_t val, bool isSigned) {
U.pVal = getClearedMemory(getNumWords());
U.pVal[0] = val;
if (isSigned && int64_t(val) < 0)
for (unsigned i = 1; i < getNumWords(); ++i)
U.pVal[i] = WORDTYPE_MAX;
clearUnusedBits();
}
此函数从 val
变量复制值并将位填充到 numBits
。
这是必要的,因为负值存储为二进制补码。如果设置isSigned
且val
为负值,则高位字的所有位都设置为1。
我很好奇第三个参数,来自 LLVM llvm/ADT/APInt.h
header 的 APInt(unsigned numBits, uint64_t val, bool isSigned = false)
中的布尔值 isSigned
。
无论我将其设置为什么,getActiveBits()
或 getMinSignedBits()
等函数的结果根本不会改变。
此外,如果我想获得 signed/unsigned 值,我会使用 getSExtValue()
或 getZExtValue()
。
isSigned
的价值对他们来说也不重要。
那么 isSigned
什么时候重要?
根据 docs 判断 val
是有符号还是无符号。
If isSigned is true then val is treated as if it were a signed value (i.e. as an int64_t) and the appropriate sign extension to the bit width will be done. Otherwise, no sign extension occurs (high order bits beyond the range of val are zero filled).
TL;DR: isSigned
仅对 numBits > 64
.
sizeof(val)
只有64位。想象一下,您想将带符号的值存储在具有 size > 64 bits
.
如果值为负数,所有高位必须设置为
1
,因为负值通常存储为two's complement.如果值为正数,所有高位必须设置为
0
例子
假设您要以 128 位存储 -1。
持有-1的uint64_t val
的二进制表示是
1111111111111111111111111111111111111111111111111111111111111111
这里只有64位,所以还有64位需要补齐。如果没有 isSigned
值,就无法知道这些位是否应该是 ones,从而导致 -1 或 zeros,导致 18446744073709551615.
详细解释
一看 source code 就会发现,isSigned
仅在某些情况下使用:
APInt(unsigned numBits, uint64_t val, bool isSigned = false)
: BitWidth(numBits) {
assert(BitWidth && "bitwidth too small");
if (isSingleWord()) {
U.VAL = val;
clearUnusedBits();
} else {
initSlowCase(val, isSigned);
}
}
根据its function header、isSingleWord
returns true if the number of bits <= 64, false otherwise.
因此行
if (isSingleWord()) {
检查值的存储是否占用比 val
本身更多的内存。
如果 numBits
大于 64,则调用 APInt::initSlowCase
:
void APInt::initSlowCase(uint64_t val, bool isSigned) {
U.pVal = getClearedMemory(getNumWords());
U.pVal[0] = val;
if (isSigned && int64_t(val) < 0)
for (unsigned i = 1; i < getNumWords(); ++i)
U.pVal[i] = WORDTYPE_MAX;
clearUnusedBits();
}
此函数从 val
变量复制值并将位填充到 numBits
。
这是必要的,因为负值存储为二进制补码。如果设置isSigned
且val
为负值,则高位字的所有位都设置为1。