【问题标题】:generate machine code directly via LLVM API直接通过 LLVM API 生成机器码
【发布时间】:2016-01-16 00:40:16
【问题描述】:

使用以下代码,我可以从一个模块生成一个LLVM 位码文件

llvm::Module * module;

// fill module with code
module = ...;

std::error_code ec;
llvm::raw_fd_ostream out("anonymous.bc", ec, llvm::sys::fs::F_None);

llvm::WriteBitcodeToFile(module, out);

然后我可以使用该位码文件生成可执行的机器代码文件,例如:

clang -o anonymous anonymous.bc

或者:

llc anonymous.bc
gcc -o anonymous anonymous.s

我现在的问题是:我可以直接在 C++ 中使用 LLVM API 生成机器代码,而无需首先编写位码文件吗?

我正在寻找代码示例或至少在 LLVM API 中的一些起点,例如使用哪些类,将我推向正确的方向可能就足够了。

【问题讨论】:

  • 我没听懂。您想要一个使用 LLVM 工具生成没有中间文件的机器代码的 shell 脚本,或者您想通过 LLVM API 来实现?
  • 我承认,问题的措辞模棱两可。编辑澄清:我想通过 LLVM API 来做。
  • 我投票结束这个问题作为题外话,因为这不是一个给我的代码网站。恐怕,虽然我可以轻松回答你的问题,但我肯定不会。做好自己的工作。
  • 谢谢,@Puppy,你这么有帮助,你为什么还要使用 stackoverflow?
  • 原因有很多,但是写代码给懒人复制粘贴不是其中之一。

标签: llvm llvm-c++-api


【解决方案1】:

看看llc tool source,特别是compileModule() 函数。简而言之,它创建Target,通过TargetOptions为其设置一些选项,然后将其用于addPassesToEmitFile(),最后要求PassManager执行所有计划任务。

【讨论】:

  • 谢谢,这真的很有帮助。据我所知,这样我可以输出一个“.o”或“.obj”本机目标文件,但没有链接。是否可以直接通过 LLVM 进行链接,还是仍在进行中?
  • 有 lld 项目,它执行链接,它在某些拱门(OSX 和 Linux)上非常有用。但是最近我在邮件列表上看到了关于其架构不允许将其用作库的讨论。已经决定 lld 应该提供这样的 API,但我想它仍在进行中,是的。
【解决方案2】:

我也在寻找这方面的代码,@arrowd 的建议奏效了。

为了省去下一个人的麻烦,这就是我想出的。

给定一个模块,它会在标准输出上为您的原生目标生成汇编代码:

void printASM(Module *M) {
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();

    auto TargetTriple = sys::getDefaultTargetTriple();
    M->setTargetTriple(TargetTriple);

    std::string Error;
    const Target *target = TargetRegistry::lookupTarget(TargetTriple, Error);
    auto cpu = sys::getHostCPUName();
    SubtargetFeatures Features;
    StringMap<bool> HostFeatures;
    if (sys::getHostCPUFeatures(HostFeatures))
        for (auto &F : HostFeatures)
            Features.AddFeature(F.first(), F.second);
    auto features = Features.getString();

    TargetOptions Options;
    std::unique_ptr<TargetMachine> TM{
            target->createTargetMachine(
                    TargetTriple, cpu, features, Options,
                    Reloc::PIC_, None, CodeGenOpt::None)
    };

    legacy::PassManager PM;
    M->setDataLayout(TM->createDataLayout());
    TM->addPassesToEmitFile(PM, (raw_pwrite_stream &) outs(), (raw_pwrite_stream *) (&outs()),
                            TargetMachine::CodeGenFileType::CGFT_AssemblyFile, true, nullptr);
    PM.run(*M);
}

如果有人知道编写此代码的更短方法,请随时纠正我!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    相关资源
    最近更新 更多