LLVM IR 中 bool 的数据类型
Data type for bool in LLVM IR
我正在编写一个编程语言编译器来集成 DSL 和 C/C++。为此,出于几个原因,我决定使用 LLVM。
有一个主程序。在这个主程序中,我加载了由 clang 编译的位码文件。可加载的位码文件代表一个简短但完整的编程语言环境,包括 REPL、解析器、linker 和 AST。
到目前为止,我的理解是布尔数据类型在 IR 中表示为 i1。我已经使用 -O3 优化了我的代码,并在 IR 代码之后得到了一个布尔值(通过从生成的位码文件中使用 llvm-dis 进行反汇编):
%"class.tl::contrib::toy::ToyREPL" = type <{ %"class.tl::contrib::toy::InitLanguage"*, i8, [7 x i8] }>
class 是 ToyREPL,它正在使用另一个 class InitLanguage。奇怪的是,布尔值似乎是由一个 i8 和一个 i8 数组表示的。我真的不明白。
我已经定义了一个Makefile。首先我编译文件。之后我 link 将它们写入 bc 文件,然后优化并 link 它与其他一些库。
@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
Link 标志是 -v
。
Class ToyREPL 的相关部分在这里:
class ToyREPL {
private:
InitLanguage *initLang;
bool runs = false;
现在我的问题是:我的假设是错误的 bool 应该被编译成 i1 吗?我需要考虑什么样的编译器开关才能编译为 i1?如果您认为我的构建过程在某些方面有误,请告诉我。生成的位码文件是可读的,我可以检索模块和 class ToyREPL 作为 StructType。
如果我理解正确的话,你的问题本质上是——为什么 C++ class
class ToyREPL {
bool runs = false;
...
};
由 Clang 编译成 type <{ i8, [7 x i8], ... }>
?
所以首先,为什么 Clang 选择 i8
而不是 i1
作为布尔字段很简单 - , and unless you use bit-fields, that also applies to fields in structs. Also see this related question about why a whole byte is used for booleans。 LLVM 本身使用 i1
作为布尔值,但那是因为它大致与平台无关——在降低阶段,它们可能再次变成完整字节。
至于 [7 x i8]
,这是填充,用于确保此类型的每个对象都是 64 位对齐的并且不与任何其他对象共享其内存 - 在 64 位系统上非常合理的方法。或者,如果有以下结构字段,则可能已插入填充以确保该字段是 64 位对齐的。
如果您想了解更多信息,
我正在编写一个编程语言编译器来集成 DSL 和 C/C++。为此,出于几个原因,我决定使用 LLVM。
有一个主程序。在这个主程序中,我加载了由 clang 编译的位码文件。可加载的位码文件代表一个简短但完整的编程语言环境,包括 REPL、解析器、linker 和 AST。
到目前为止,我的理解是布尔数据类型在 IR 中表示为 i1。我已经使用 -O3 优化了我的代码,并在 IR 代码之后得到了一个布尔值(通过从生成的位码文件中使用 llvm-dis 进行反汇编):
%"class.tl::contrib::toy::ToyREPL" = type <{ %"class.tl::contrib::toy::InitLanguage"*, i8, [7 x i8] }>
class 是 ToyREPL,它正在使用另一个 class InitLanguage。奇怪的是,布尔值似乎是由一个 i8 和一个 i8 数组表示的。我真的不明白。
我已经定义了一个Makefile。首先我编译文件。之后我 link 将它们写入 bc 文件,然后优化并 link 它与其他一些库。
@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
Link 标志是 -v
。
Class ToyREPL 的相关部分在这里:
class ToyREPL {
private:
InitLanguage *initLang;
bool runs = false;
现在我的问题是:我的假设是错误的 bool 应该被编译成 i1 吗?我需要考虑什么样的编译器开关才能编译为 i1?如果您认为我的构建过程在某些方面有误,请告诉我。生成的位码文件是可读的,我可以检索模块和 class ToyREPL 作为 StructType。
如果我理解正确的话,你的问题本质上是——为什么 C++ class
class ToyREPL {
bool runs = false;
...
};
由 Clang 编译成 type <{ i8, [7 x i8], ... }>
?
所以首先,为什么 Clang 选择 i8
而不是 i1
作为布尔字段很简单 - i1
作为布尔值,但那是因为它大致与平台无关——在降低阶段,它们可能再次变成完整字节。
至于 [7 x i8]
,这是填充,用于确保此类型的每个对象都是 64 位对齐的并且不与任何其他对象共享其内存 - 在 64 位系统上非常合理的方法。或者,如果有以下结构字段,则可能已插入填充以确保该字段是 64 位对齐的。