Reputation: 508
With the following code, I can generate an LLVM bitcode file from a module:
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);
I can then use that bitcode file to generate an executable machine code file, e.g.:
clang -o anonymous anonymous.bc
Alternatively:
llc anonymous.bc
gcc -o anonymous anonymous.s
My question now is: Can I generate the machine code directly in C++ with the LLVM API without first needing to write the bitcode file?
I am looking for either a code example or at least some starting points in the LLVM API, e.g. which classes to use, nudging me in the right direction might even be enough.
Upvotes: 4
Views: 1501
Reputation: 147
I was also looking for the code for this, and @arrowd's suggestion worked.
To save the trouble for the next person, this is what I came up with.
Given a Module, it generates assembly code on stdout for your native target:
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);
}
If anyone knows a shorter way to write this code, feel free to correct me!
Upvotes: 6
Reputation: 34421
Take a look at llc tool source, spcifically compileModule()
function. In short, it creates Target
, sets some options for it via TargetOptions
, then uses it to addPassesToEmitFile()
and finally asks PassManager
to perform all planned tasks.
Upvotes: 3