LLVM IR中bool类型的数据类型

4
我正在编写一种编程语言的编译器,以将DSL与C/C++集成。出于几个原因,我决定使用LLVM。
有一个主程序。在这个主程序中,我加载由clang编译的位码文件。可加载的位码文件代表了一个短小但完整的编程语言环境,包括REPL、解析器、链接器和AST。
迄今为止我的理解是布尔数据类型在IR中被表示为i1。我已经使用-O3对我的代码进行了优化,并且我得到了以下用于布尔的IR代码(通过从生成的位码文件中反汇编得到):
%"class.tl::contrib::toy::ToyREPL" = type <{  %"class.tl::contrib::toy::InitLanguage"*, i8, [7 x i8] }>

这个类名为ToyREPL,它使用了另一个叫做InitLanguage的类。奇怪的是,布尔变量似乎由i8和i8数组表示。我真的不太理解。

我已经定义了一个Makefile。首先我编译文件。然后将它们链接到一个bc文件,并优化并与一些其他库链接。

@cd $(BIN)/$(TARGET)/$(2); $(LINK) -o $(1).$(BITCODE_EXT) $(3)

@cd $(BIN)/$(TARGET)/$(2); $(OPT) -O3 $(1).$(BITCODE_EXT) -o $(1).$(OPT_NAME).$(BITCODE_EXT) $(OPTIMIZER_FLAGS) 

@$(LINK) -o $(BIN)/$(TARGET)/$(2)/$(1).$(BITCODE_EXT) $(BIN)/$(TARGET)/$(2)/$(1).$(OPT_NAME).bc $(LINK_OPTION) $(4)

编译器标志是:
-v -g -emit-llvm -I$(BOOST_INC_DIR) -std=c++11 -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS

优化器标志为-std-link-opts

链接标志为-v

类ToyREPL的相关部分在此处:

class ToyREPL {
private:

  InitLanguage *initLang;

  bool runs = false;

现在我的问题是:我的假设是错误的,bool 应该被编译为 i1 吗?我需要考虑哪种编译器开关来编译为 i1?如果你认为我的构建过程有问题,请让我知道。生成的 bitcode 文件是可读的,我可以检索到模块和类 ToyREPL 作为 StructType。


用代码替换引号--引号通常最适合引用人类编写的内容,而不是计算机。 ;) - Yakk - Adam Nevraumont
1个回答

6

如果我理解正确,您的问题本质上是 - 为什么C++类被创建为抽象类?

class ToyREPL {
  bool runs = false;
  ...
};

由Clang编译成type <{ i8, [7 x i8], ... }>
首先,为什么Clang在布尔字段中选择i8而不是i1很简单 - 最小的C ++类型需要一个字节的内存,除非您使用位域,否则结构体中的字段也适用于此。有关布尔值使用整个字节的原因,请参见这个相关问题。LLVM本身对布尔值使用i1,但这是因为它大致上是平台无关的 - 在降级阶段,它们可能再次变成整个字节。
至于[7 x i8],那是填充,用来确保此类型的每个对象都是64位对齐的,并且不与任何其他对象共享其内存 - 在64位系统上非常合理。或者,如果有以下结构字段,则可能插入填充以确保该字段为64位对齐。
如果您想了解更多信息,请参见关于对齐和填充的维基百科文章

这似乎是显而易见的答案……但 LLVM 是否没有任何例外,或者大多数问题仅源于 C++ 的规范方式? - CinchBlue
谢谢。填充对我来说很有意义,因为我有一台64位的计算机。但这意味着如果我没有手头上的位码,我永远无法区分一个整数值和一个布尔值,是吗? - repl
@VermillionAzure,据我所知,这全部来自Clang,因为C++的规范和性能原因。例如,另一种语言可能会强制使用“i1”作为布尔值以节省空间-但是降低阶段可能会做出奇怪的事情,以便在具有字节寻址的机器上加载和存储“i1”。 - Oak
@repl 你可以通过观察它的使用方式来判断...但总的来说,我想你是对的,没有办法确定。如果这对你很重要,你可以随时打开调试信息,那应该提供有关每个字段声明类型的所有信息。 - Oak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接