APInt(unsigned numBits, uint64_t val, bool isSigned = false)



我对第三个参数很好奇,即来自 LLVMllvm/ADT/APInt.h标头的布尔isSignedAPInt(unsigned numBits, uint64_t val, bool isSigned = false)

无论我将其设置为什么,getActiveBits()getMinSignedBits()等函数的结果都不会改变。

此外,如果我想获取有符号/无符号值,我使用getSExtValue()getZExtValue().

isSigned的价值对他们来说也不重要。

那么isSigned什么时候重要呢?

TL;DR:isSigned只对numBits > 64很重要。

sizeof(val)只有 64 位。假设您要将有符号值存储在带有size > 64 bits的整数中。

  • 如果该值为负值,则必须将所有高位设置为1,因为负值通常存储为 2 的补码。

  • 如果该值为正,则必须将所有高位设置为0

假设您想以 128 位存储-1

持有-1uint64_t val的二进制表示为

1111111111111111111111111111111111111111111111111111111111111111

这只是 64个,所以还有 64 位需要填充。如果没有isSigned值,就不可能知道这些位应该是1,从而导致-1还是,从而导致18446744073709551615

详细解释

从源代码中可以看出,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);
}
}

根据其函数标头,isSingleWord

如果位数 <= 64,则返回 true,否则返回 false。

因此,该行

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。

根据文档可以告诉val是有符号还是无符号。

如果 isSigned 为 true,则 val 被视为有符号值(即作为int64_t(,并且将对位宽进行适当的符号扩展。否则,不会发生符号扩展(超出 val 范围的高阶位为零填充(。

最新更新