I'm currently working on a compiler project using llvm. I have followed various tutorials to the point where I have a parser to create a syntax tree and then the tree is converted into an llvm Module using the provided IRBuilder.
我目前正在使用llvm编写一个编译器项目。我已经遵循了各种教程,我有一个解析器来创建语法树,然后使用提供的IRBuilder将树转换为llvm模块。
My goal is to create an executable, and I am confused as what to do next. All the tutorials I've found just create the llvm module and print out the assembly using Module.dump(). Additionally, the only documentation I can find is for llvm developers, and not end users of the project.
我的目标是创建一个可执行文件,我很困惑,接下来该做什么。我发现的所有教程都是创建llvm模块并使用Module.dump()打印出程序集。另外,我能找到的唯一文档是llvm开发人员,而不是项目的最终用户。
If I want to generate machine code, what are the next steps? The llvm-mc project looks like it may do what I want, but I can't find any sort of documentation on it.
如果我想生成机器代码,接下来的步骤是什么? llvm-mc项目看起来可能会做我想要的,但我找不到任何类型的文档。
Perhaps I'm expecting llvm to do something that it doesn't. My expectation is that I can build a Module, then there would be an API that I can call with the Module and a target triple and an object file will be produced. I have found documentation and examples on producing a JIT, and I am not interested in that. I am looking for how to produce compiled binaries.
也许我期待自己会做一些事情。我的期望是我可以构建一个模块,然后会有一个我可以使用模块调用的API,并且将生成目标三元组和一个目标文件。我找到了关于生成JIT的文档和示例,我对此并不感兴趣。我正在寻找如何生成编译的二进制文件。
I am working on OS X, if that has any impact.
我正在研究OS X,如果这有任何影响。
4 个解决方案
#1
15
Use llc -filetype=obj
to emit a linkable object file from your IR. You can look at the code of llc
to see the LLVM API calls it makes to emit such code. At least for Mac OS X and Linux, the objects emitted in such a manner should be pretty good (i.e. this is not a "alpha quality" option by now).
使用llc -filetype = obj从IR发出可链接的目标文件。您可以查看llc的代码,以查看它发出的LLVM API调用以发出此类代码。至少对于Mac OS X和Linux,以这种方式发出的对象应该非常好(即,现在这不是“alpha质量”选项)。
LLVM does not contain a linker (yet!), however. So to actually link this object file into some executable or shared library, you will need to use the system linker. Note that even if you have an executable consisting of a single object file, the latter has to be linked anyway. Developers in the LLVM community are working on a real linker for LLVM, called lld
. You can visit its page or search the mailing list archives to follow its progress.
但是,LLVM不包含链接器(但是!)。因此,要将此对象文件实际链接到某个可执行文件或共享库,您需要使用系统链接器。请注意,即使您有一个由单个目标文件组成的可执行文件,也必须将后者链接起来。 LLVM社区中的开发人员正在为LLVM开发一个真正的链接器,称为lld。您可以访问其页面或搜索邮件列表存档以跟踪其进度。
#2
14
As you can read on the llc guide, it is indeed intended to just generate the assembly, and then "The assembly language output can then be passed through a native assembler and linker to generate a native executable" - e.g. the gnu assembler (as
) and linker (ld
).
正如您可以在llc指南上阅读的那样,它确实只是生成程序集,然后“然后可以通过本机汇编程序和链接程序传递汇编语言输出以生成本机可执行文件” - 例如gnu汇编程序(as)和链接器(ld)。
So the main answer here is to use native tools for assembling and linking.
所以这里的主要答案是使用本机工具进行组装和链接。
However, there's experimental support for generating the native object directly from an IR file, via llc
:
但是,有通过llc直接从IR文件生成本机对象的实验性支持:
-filetype - Choose a file type (not all types are supported by all targets):
=asm - Emit an assembly ('.s') file
=obj - Emit a native object ('.o') file [experimental]
Or you can use llvm-mc
to assemble it from the .s
file:
或者您可以使用llvm-mc从.s文件中组装它:
-filetype - Choose an output file type:
=asm - Emit an assembly ('.s') file
=null - Don't emit anything (for timing purposes)
=obj - Emit a native object ('.o') file
I don't know about linkers, though.
不过,我不知道链接器。
In addition, I recommend checking out the tools/bugpoint/ToolRunner.h
file, which exposes a wrapper combining llc
and the platform's native C toolchain for generating machine code. From its header comment:
此外,我建议查看tools / bugpoint / ToolRunner.h文件,该文件公开了一个包装器,它结合了llc和平台的本机C工具链,用于生成机器代码。从标题评论:
This file exposes an abstraction around a platform C compiler, used to compile C and assembly code.
该文件公开了一个围绕平台C编译器的抽象,用于编译C和汇编代码。
#3
4
Check out these functions in llvm-c/TargetMachine.h
:
在llvm -c / TargetMachine.h中查看这些函数:
/** Emits an asm or object file for the given module to the filename. This
wraps several c++ only classes (among them a file stream). Returns any
error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);
/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */
LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M,
LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf);
#4
1
To run the example BrainF
program, compile it and run:
要运行示例BrainF程序,请编译并运行:
echo ,. > test.bf
./BrainF test.bf -o test.bc
llc -filetype=obj test.bc
gcc test.o -o a.out
./a.out
then type a single letter and press Enter. It should echo that letter back to you. (That's what ,.
does.)
然后键入单个字母并按Enter键。它应该将这封信回复给你。 (那是什么,。)。
The above was tested with LLVM version 3.5.0.
以上是使用LLVM版本3.5.0测试的。
#1
15
Use llc -filetype=obj
to emit a linkable object file from your IR. You can look at the code of llc
to see the LLVM API calls it makes to emit such code. At least for Mac OS X and Linux, the objects emitted in such a manner should be pretty good (i.e. this is not a "alpha quality" option by now).
使用llc -filetype = obj从IR发出可链接的目标文件。您可以查看llc的代码,以查看它发出的LLVM API调用以发出此类代码。至少对于Mac OS X和Linux,以这种方式发出的对象应该非常好(即,现在这不是“alpha质量”选项)。
LLVM does not contain a linker (yet!), however. So to actually link this object file into some executable or shared library, you will need to use the system linker. Note that even if you have an executable consisting of a single object file, the latter has to be linked anyway. Developers in the LLVM community are working on a real linker for LLVM, called lld
. You can visit its page or search the mailing list archives to follow its progress.
但是,LLVM不包含链接器(但是!)。因此,要将此对象文件实际链接到某个可执行文件或共享库,您需要使用系统链接器。请注意,即使您有一个由单个目标文件组成的可执行文件,也必须将后者链接起来。 LLVM社区中的开发人员正在为LLVM开发一个真正的链接器,称为lld。您可以访问其页面或搜索邮件列表存档以跟踪其进度。
#2
14
As you can read on the llc guide, it is indeed intended to just generate the assembly, and then "The assembly language output can then be passed through a native assembler and linker to generate a native executable" - e.g. the gnu assembler (as
) and linker (ld
).
正如您可以在llc指南上阅读的那样,它确实只是生成程序集,然后“然后可以通过本机汇编程序和链接程序传递汇编语言输出以生成本机可执行文件” - 例如gnu汇编程序(as)和链接器(ld)。
So the main answer here is to use native tools for assembling and linking.
所以这里的主要答案是使用本机工具进行组装和链接。
However, there's experimental support for generating the native object directly from an IR file, via llc
:
但是,有通过llc直接从IR文件生成本机对象的实验性支持:
-filetype - Choose a file type (not all types are supported by all targets):
=asm - Emit an assembly ('.s') file
=obj - Emit a native object ('.o') file [experimental]
Or you can use llvm-mc
to assemble it from the .s
file:
或者您可以使用llvm-mc从.s文件中组装它:
-filetype - Choose an output file type:
=asm - Emit an assembly ('.s') file
=null - Don't emit anything (for timing purposes)
=obj - Emit a native object ('.o') file
I don't know about linkers, though.
不过,我不知道链接器。
In addition, I recommend checking out the tools/bugpoint/ToolRunner.h
file, which exposes a wrapper combining llc
and the platform's native C toolchain for generating machine code. From its header comment:
此外,我建议查看tools / bugpoint / ToolRunner.h文件,该文件公开了一个包装器,它结合了llc和平台的本机C工具链,用于生成机器代码。从标题评论:
This file exposes an abstraction around a platform C compiler, used to compile C and assembly code.
该文件公开了一个围绕平台C编译器的抽象,用于编译C和汇编代码。
#3
4
Check out these functions in llvm-c/TargetMachine.h
:
在llvm -c / TargetMachine.h中查看这些函数:
/** Emits an asm or object file for the given module to the filename. This
wraps several c++ only classes (among them a file stream). Returns any
error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);
/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */
LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M,
LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf);
#4
1
To run the example BrainF
program, compile it and run:
要运行示例BrainF程序,请编译并运行:
echo ,. > test.bf
./BrainF test.bf -o test.bc
llc -filetype=obj test.bc
gcc test.o -o a.out
./a.out
then type a single letter and press Enter. It should echo that letter back to you. (That's what ,.
does.)
然后键入单个字母并按Enter键。它应该将这封信回复给你。 (那是什么,。)。
The above was tested with LLVM version 3.5.0.
以上是使用LLVM版本3.5.0测试的。