Search code examples
c++compiler-constructionllvmllvm-c++-api

Printing LLVM IR with c++ API for debugging IR generation


I am currently working with the LLVM 12 C++ API to convert a custom design specific language to LLVM IR code. However I am running into some bugs in IR code generated.

Could you point me in the right direction, to see how I can print out the generated IR code that is contained in my llvm::Module.

I tried using this minimal example code

#include <iostream>
#include "llvm/ADT/APFloat.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/IRPrintingPasses.h"

int main(){
    // initialize the context, builder and module
    llvm::LLVMContext TheContext;
    llvm::IRBuilder<> Builder(TheContext);
    std::unique_ptr<llvm::Module> TheModule;
    TheModule = std::make_unique<llvm::Module>("my jit module", TheContext);    

    // generate an example IR code 
    /* (in reality this will be complex code running through the 
    language AST and making appropriate calls to the Builder 
    to add the IR instructions) */
    auto L = llvm::ConstantFP::get(TheContext, llvm::APFloat(5.0));
    auto R = llvm::ConstantFP::get(TheContext, llvm::APFloat(7.0));
    auto IR = Builder.CreateFAdd(L, R, "addtmp");

    IR->print(llvm::errs()); // method 0 for printing IR
    fprintf(stderr,"\n");
    // outputs:    "double 1.200000e+01"
    // method 0 is unacceptable, as I would have to manually manage the 
    // printing calls and their printing order after each call to generate an IR instruction
    // this manual way of managing can easily lead to
    // out of order printing or omissions in printing, leading to further confusion in the debug process


    // now the IR generation is completed
    // print out the IR code contained in TheModule
    TheModule->print(llvm::errs(),nullptr,false,true); // method 1
    // and
    TheModule->dump(); // method 2
    // and
    llvm::errs()<< *TheModule; // method 3
    // and
    std::unique_ptr<llvm::legacy::PassManager> TheMPM;
    TheMPM = std::make_unique<llvm::legacy::PassManager>();
    TheMPM->add(llvm::createPrintModulePass(llvm::errs()));
    TheMPM->run(*TheModule);  // method 4

    // Perform JIT compilation of the IR code 
    // (this works fine but am getting incorrect results
    // and hence want to print out the IR code to see if 
    // I am getting what I assume I should be getting)
    return 0;
}

However all four methods just give me a standard output that looks like

; ModuleID = 'my jit module'
source_filename = "my jit module"

and no IR code is shown. I know the module has IR code as I can successfully JIT compile the module and run the code.

Could you point me to the right way I could get the LLVM IR contained in the module to print out?


Solution

  • (First, excuse my stupid comment. I was killing time in a queue and obviously my mind wasn't really engaged. Back at my desk now.)

    Your code creates a module, two constant numbers and an addition. However, an addition can either be a constant or an instruction. If the latter, then the instruction needs to be in a basic block, the block in a function, and the function in a module. LLVM offers no way to have an instruction in a module but outside all functions.

    Since you don't have a function (and basic block), it follows that your addition necessarily is a constant.

    I suggest that you create two functions, a(float) and b(), make b() call a(7.0), put the addition in a's entry block and make it add 5.0 to a's argument instead of 5.0+7.0. That way you'll be sure that the addition created cannot be constant.