8.万花筒:编译为目标代码

    • 第8章简介
    • 选择目标
    • 目标机器
    • 配置模块
    • 发射对象代码
    • 把它放在一起
    • 完整的代码清单

    8.2。选择目标

    LLVM本身支持交叉编译。您可以编译到当前计算机的体系结构,也可以轻松编译其他体系结构。在本教程中,我们将以当前计算机为目标。

    要指定要定位的体系结构,我们使用称为“目标三元组”的字符串。这采用的形式 ---(参见交叉编译文档)。

    举个例子,我们可以看到clang认为我们当前的目标三元组:

    运行此命令可能会在您的计算机上显示不同的内容,因为您可能正在使用不同的体系结构或操作系统。

    幸运的是,我们不需要硬编码目标三元组来定位当前机器。LLVM提供sys::getDefaultTargetTriple,返回当前计算机的目标三元组。

    LLVM不要求我们链接所有目标功能。例如,如果我们只是使用JIT,我们不需要组装打印机。同样,如果我们仅针对某些体系结构,我们只能链接这些体系结构的功能。

    1. InitializeAllTargetInfos();
    2. InitializeAllTargets();
    3. InitializeAllTargetMCs();
    4. InitializeAllAsmParsers();

    我们现在可以使用我们的目标三元组来获得Target:

    1. std::string Error;
    2. auto Target = TargetRegistry::lookupTarget(TargetTriple, Error);
    3. // Print an error and exit if we couldn't find the requested target.
    4. // This generally occurs if we've forgotten to initialise the
    5. // TargetRegistry or we have a bogus target triple.
    6. if (!Target) {
    7. errs() << Error;
    8. return 1;

    对于我们的示例,我们将使用通用CPU,而无需任何其他功能,选项或重定位模型。

    1. auto CPU = "generic";
    2. auto Features = "";
    3. TargetOptions opt;
    4. auto RM = Optional<Reloc::Model>();
    5. auto TargetMachine = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);

    8.4 配置模块

    我们现在准备配置我们的模块,以指定目标和数据布局。这不是绝对必要的,但前端性能指南建议这样做。通过了解目标和数据布局,优化得益。

    1. TheModule->setDataLayout(TargetMachine->createDataLayout());
    2. TheModule->setTargetTriple(TargetTriple);

    我们准备发出目标代码了!让我们定义我们要将文件写入的位置:

    1. auto Filename = "output.o";
    2. raw_fd_ostream dest(Filename, EC, sys::fs::F_None);
    3. if (EC) {
    4. errs() << "Could not open file: " << EC.message();
    5. }

    8.6 全部放在一起

    1. $ clang++ -g -O3 toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs all` -o toy

    让我们运行它,并定义一个简单的average函数。完成后按Ctrl-D。

    1. $ ./toy
    2. ready> def average(x y) (x + y) * 0.5;
    3. ^D
    4. Wrote output.o

    我们有一个目标文件!为了测试它,让我们编写一个简单的程序并将其与我们的输出链接。这是源代码:

    1. #include <iostream>
    2. extern "C" {
    3. double average(double, double);
    4. }
    5. int main() {
    6. std::cout << "average of 3.0 and 4.0: " << average(3.0, 4.0) << std::endl;

    我们将程序链接到output.o并检查结果是否符合我们的预期:

    这是代码:

    下一页:添加调试信息