通过LLVM API直接生成机器代码

通过LLVM API直接生成机器代码,llvm,llvm-c++-api,Llvm,Llvm C++ Api,使用以下代码,我可以从模块生成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); 然后,我可以使用该位代码文件生成可执行的机器代码文件,例如:

使用以下代码,我可以从模块生成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

我现在的问题是:我可以用LLVM API直接生成C++中的机器代码而不需要首先编写位代码文件吗?
我正在寻找一个代码示例,或者至少是LLVM API中的一些起始点,例如,使用哪些类,将我推向正确的方向可能就足够了。

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

我也在为此寻找代码,@arrowd的建议奏效了

为了给下一个人省事,这是我想到的

给定一个模块,它会在stdout上为本机目标生成汇编代码:

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);
}
void printASM(模块*M){
InitializeEnableTarget();
InitializeEnableTargetAsmPrinter();
auto-TargetTriple=sys::getDefaultTargetTriple();
M->setTargetTriple(TargetTriple);
字符串错误;
const Target*Target=TargetRegistry::lookupTarget(TargetTriple,错误);
自动cpu=sys::getHostCPUName();
子目标特征;
地图特征;
if(sys::gethostcpuffeatures(HostFeatures))
用于(自动&F:HostFeatures)
addFeatures(F.first(),F.second);
自动特征=特征。getString();
目标选项选项;
标准::唯一的{
目标->创建目标机器(
TargetTriple、cpu、功能、选项、,
Reloc::PIC(无,无,CodeGenOpt::无)
};
遗产:PassManager PM;
M->setDataLayout(TM->createDataLayout());
TM->AddPasseToEmitFile(PM,(原始写入流和)输出(),(原始写入流*)(&outs()),
TargetMachine::CodeGenFileType::CGFT_AssemblyFile,true,nullptr);
PM.run(*M);
}

如果有人知道写这段代码的较短方法,请随时纠正我

我不明白。你想要一个使用LLVM工具生成机器代码而不需要中间文件的shell脚本,还是想通过LLVM API来实现?我承认,这个问题的措辞是模棱两可的。编辑澄清:我想通过LLVM API来解决这个问题。我投票结束这个问题,因为这不是给我一个codez网站。恐怕,虽然我能轻松地回答你的问题,但我肯定不会。做你自己的工作。谢谢,@Puppy,你真的很有帮助,为什么还要使用stackoverflow呢?原因有很多,但为懒惰的人编写代码进行复制和粘贴并不是其中之一。谢谢,这真的很有帮助。就我所见,这样我可以输出一个“.o”或“.obj”本机对象文件,但没有链接。链接可以通过LLVM直接完成吗?还是仍在工作中?有一个lld项目,它执行链接,在一些拱门(OSX和Linux)上非常有用。但最近我在邮件列表上看到了一个关于其体系结构不允许将其用作库的讨论。已经决定lld应该提供这样的API,但我想这仍然是一项正在进行的工作,是的。