4

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.

Urist McDev
  • 498
  • 3
  • 14
  • 1
    I didn't get it. You want a shell script that uses LLVM tools to generate machine code without intermediate files, or you want to do it via LLVM API? – arrowd Jan 16 '16 at 12:20
  • I admit, the wording of the question was ambiguous. Edited to clarify: I want to do it via the LLVM API. – Urist McDev Jan 16 '16 at 12:26
  • I'm voting to close this question as off-topic because this is not a give-me-the-codez website. I'm afraid that, although I can answer your question with ease, I certainly won't. Do your own job. – Puppy Jan 16 '16 at 12:27
  • 2
    Thanks, @Puppy, you are so very helpful, why are you even using stackoverflow? – Urist McDev Jan 16 '16 at 12:30
  • There are many reasons, but to write code for lazy people to copy and paste is not one of them. – Puppy Jan 16 '16 at 12:31
  • Copy and paste where from? I've searched and didn't find anything. Don't you at least care to put me on to something? – Urist McDev Jan 16 '16 at 12:32
  • https://stackoverflow.com/a/33900895/432 – andrewrk Sep 19 '18 at 18:45

2 Answers2

5

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!

youneverknow
  • 137
  • 2
  • 8
3

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.

arrowd
  • 33,231
  • 8
  • 79
  • 110
  • Thanks, that really helped. As far as I can see, this way I can output a "*.o" or "*.obj" native object file, but there is no linking. Can linking be done directly via LLVM yet, or is that still in the works? – Urist McDev Jan 17 '16 at 17:55
  • There is lld project, which performs linking and it is quite usable on some arches (OSX and Linux). But recently i saw a discussion on the mailing list regarding its architecture not allowing using it as library. It has been decided that lld should provide such API, but i suppose it's still a work-in-progress, yes. – arrowd Jan 17 '16 at 20:11