Search code examples
llvmclang++llvm-clangllvm-irllvm-3.0

Get filename and location from Function


I have an LLVM pass that iterates over LLVM IR code and I would like to get a directory and a filename for both the functions and basic blocks for the original code. I know that when I have an Instruction Pointer, I can easily get the information using the code below: Thanks to @hailinzeng (How to get the filename and directory from a LLVM Instruction?)

const llvm::DebugLoc &location = i_iter->getDebugLoc();

if (location && debugLocationInfoOn) {
  std::string dbgInfo;
  llvm::raw_string_ostream rso(dbgInfo);
  location.print(rso);
  std::cout << rso.str();
}

However, since the class Function and BasicBlock do not have a member function getDebugLoc(), this doesn't work. I saw another post here using the metadata but I do not know how to get to the DILocation or DIScope from the metadata. Using

MDNode *n = inst->getMetadata("dbg");
DILocation loc(n);   `

Gives the error below

/usr/lib/llvm-3.9/include/llvm/IR/Metadata.def:83:42: note: forward declaration of 'llvm::DILocation' HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)

I'm using llvm 3.9.

UPDATE :: Thanks Stanislav Pankevich. I wasn't including the right headers but now I have a new issue. DILocation requires LLVMContext, StorageType, and unsigned Line. How do I get the line number and and storage type from a function pointer? DILocation(LLVMContext &C, StorageType Storage, unsigned Line,

For those working with a similar issue, you can get LLVMContext using

llvm::MDNode * testmd = F.getMetadata("dbg");
F.getContext ()

Solution

  • If you look at the .ll file for your code, you would see that every function has DINode associated with it, something like !<some_number>. That's the metadata node number that is has info about that function. The type of that node is DISubprogram You can access it like this:

    SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
    F.getAllMetadata(MDs);
    for (auto &MD : MDs) {
      if (MDNode *N = MD.second) {
        if (auto *subProgram = dyn_cast<DISubprogram>(N)) {
          errs() << subProgram->getLine();
        }
      }
    }
    

    You can use all the information that is there in the debug node.