LLVM如何做AOT编译
LLVM how to do AOT compilation
我正在尝试使用 LLVM 创建一种玩具语言
目前,我可以使用我的 LLVM IR 发出文件,但我不知道如何将其静态编译成可执行文件。 LLVM教程用的是JIT编译,我想做AOT编译
我该怎么做?
如果您已经生成了 LLVM IR,您可以先通过 LLC 将 IR 代码生成为机器代码,然后 link 将目标文件生成为可执行文件。
如果你想通过命令行使用它,只需
clang yourIRFile.ll -o output
或
llc yourIRFile.ll --filetype=obj
lld generatedObjFileName.o -o output
否则,您可以使用 llc
和 lld
api。
(以下关键代码摘自其tools目录下的llc.cpp
和lld.cpp
,所有代码均为本人验证)
首先,对于代码生成,使用 target machine pass
by
legacy::PassManager pass;
auto CPU = "generic";
auto Features = "";
std::string Error;
auto Target = TargetRegistry::lookupTarget(module->getTargetTriple(), Error);
TheTargetMachine =
Target->createTargetMachine(module->getTargetTriple(), CPU, Features, targetOptions, RM);
assert(TheTargetMachine && "Fail to create TheTargetMachine");
auto FileType = CGFT_ObjectFile;
SmallVector<char, 0> objStream;
std::unique_ptr<raw_svector_ostream> BOS = std::make_unique<raw_svector_ostream>(objStream);
auto OS = BOS.get();
if (TheTargetMachine->addPassesToEmitFile(pass, *OS, nullptr, FileType)) {
errs() << "TheTargetMachine can't emit a file of this type";
return;
}
// Here write the `objStream` content to a temp file you like.
// the objStream is the object file need by lld linker
然后使用lld linker
const char *emu_argv[] = {
"ld.lld",
objFileName,
"-o",
execFileName,
};
int argc = sizeof(emu_argv) / sizeof(emu_argv[0]);
const char **argv = (const char **) emu_argv;
std::vector<const char *> args(argv, argv + argc);
lld::elf::link(args, false, outs(), outs());
objFileName
是您在 codegen 生成的文件。
最后,execFileName
就是最终的可执行文件。
我正在尝试使用 LLVM 创建一种玩具语言
目前,我可以使用我的 LLVM IR 发出文件,但我不知道如何将其静态编译成可执行文件。 LLVM教程用的是JIT编译,我想做AOT编译
我该怎么做?
如果您已经生成了 LLVM IR,您可以先通过 LLC 将 IR 代码生成为机器代码,然后 link 将目标文件生成为可执行文件。
如果你想通过命令行使用它,只需
clang yourIRFile.ll -o output
或
llc yourIRFile.ll --filetype=obj
lld generatedObjFileName.o -o output
否则,您可以使用 llc
和 lld
api。
(以下关键代码摘自其tools目录下的llc.cpp
和lld.cpp
,所有代码均为本人验证)
首先,对于代码生成,使用 target machine pass
by
legacy::PassManager pass;
auto CPU = "generic";
auto Features = "";
std::string Error;
auto Target = TargetRegistry::lookupTarget(module->getTargetTriple(), Error);
TheTargetMachine =
Target->createTargetMachine(module->getTargetTriple(), CPU, Features, targetOptions, RM);
assert(TheTargetMachine && "Fail to create TheTargetMachine");
auto FileType = CGFT_ObjectFile;
SmallVector<char, 0> objStream;
std::unique_ptr<raw_svector_ostream> BOS = std::make_unique<raw_svector_ostream>(objStream);
auto OS = BOS.get();
if (TheTargetMachine->addPassesToEmitFile(pass, *OS, nullptr, FileType)) {
errs() << "TheTargetMachine can't emit a file of this type";
return;
}
// Here write the `objStream` content to a temp file you like.
// the objStream is the object file need by lld linker
然后使用lld linker
const char *emu_argv[] = {
"ld.lld",
objFileName,
"-o",
execFileName,
};
int argc = sizeof(emu_argv) / sizeof(emu_argv[0]);
const char **argv = (const char **) emu_argv;
std::vector<const char *> args(argv, argv + argc);
lld::elf::link(args, false, outs(), outs());
objFileName
是您在 codegen 生成的文件。
最后,execFileName
就是最终的可执行文件。