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 headerAPInt(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

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

1111111111111111111111111111111111111111111111111111111111111111

这里只有64位,所以还有64位需要补齐。如果没有 isSigned 值,就无法知道这些位是否应该是 ones,从而导致 -1zeros,导致 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 headerisSingleWord

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

这是必要的,因为负值存储为二进制补码。如果设置isSignedval为负值,则高位字的所有位都设置为1。