LLVM 是否在其整数常量的类型规则中做出了例外?

Does LLVM make an exception in its type rules for integer constants?

我正在尝试弄清楚 LLVM 中类型的确切规则。据我了解,一般规则是运营商,例如add 必须接受两个 T 类型的操作数,并且 return 也是 T 类型的结果。但是,整数常量似乎是一个例外。

根据https://llvm.org/docs/LangRef.html#simple-constants

Standard integers (such as ‘4’) are constants of the integer type.

单词 'integer' 链接到

The integer type is a very simple type that simply specifies an arbitrary bit width for the integer type desired. Any bit width from 1 bit to 223(about 8 million) can be specified.

所以它没有说明给定常量最终的整数类型的宽度。

查看 LLVM 源代码,它包含一个名为 APInt 的 class,任意精度整数,https://llvm.org/doxygen/classllvm_1_1APInt.html 这似乎表明整数常量存储为任意精度。

用 clang 进行的一些实验生成了这条指令:

store i128 -1844674407370955161510, i128* %3, align 16, !tbaa !3

它确实有一个 128 位整数常量,没有 C 需要的任何特殊后缀来指示其类型。

但是整数常量也可以是算术运算的操作数。

这是否意味着完整类型规则类似于“运算符必须采用 T 类型的操作数,并且 return 结果也是 T 类型,除非其中一个操作数是整数常量,在哪种情况不需要遵循该规则?

编辑: 好的,进一步深入了解解析器的作用...

LLLexer.cpp 在我正在查看的版本的第 1121 行,这似乎是它对整数常量标记进行词法分析的地方:

  // If the next character is a '.', then it is a fp value, otherwise its
  // integer.
  if (CurPtr[0] != '.') {
    if (TokStart[0] == '0' && TokStart[1] == 'x')
      return Lex0x();
    APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart));
    return lltok::APSInt;
  }

所以它正在创建一个没有附加位宽的 APSInt(任意精度带符号整数)。

不,它没有例外。

获得常量整数的唯一方法是调用 get()/getTrue()/... 中的一个函数 ConstantInt,您会注意到它们都采用具有显式位宽的类型,或具有隐式类型(IIRC bool 是唯一的例子,但我可能忘记了一些东西)。

根据 IRC 上的 jrtc27,所有操作数都必须具有为操作指定的类型,因此常量操作数被认为具有该类型。