Print out inline function programmably

Hello guys,
I am new to llvm, I am trying to create llvm pass that can print out inlined functions, I tried with this but does not work.
Is there such condition that I missed? I know I can know the function got inlined when compile the program using clang with this flags -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline, but I want to implement it programiticly


#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h"
#include <set>

using namespace llvm;

namespace {
  struct InlineFunctionPass : public FunctionPass {
    static char ID;
    InlineFunctionPass() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
      std::set<Function*> inlined_functions;

      for (BasicBlock &BB : F) {
       
        for (Instruction &I : BB) {
          if (CallInst *CI = dyn_cast<CallInst>(&I)) {
            if (CI->isInlineAsm()) {
              // Skip inline assembly calls.
              continue;
            }
            if (Function *Callee = CI->getCalledFunction()) {
              errs() << "function captured before conditions: " << Callee->getName() << '\n';
              if (Callee->isDeclaration()) {
                // Skip external function calls.
                continue;
              }
              if (Callee->hasFnAttribute(Attribute::NoInline)) {
                // Skip functions that are marked as not inlineable.
                continue;
              }
              if (Callee->getMetadata("inline") == nullptr) {
                // Skip functions that have not been marked as inline.
                continue;
              }
              inlined_functions.insert(Callee);
            }
          }
        }
      }

      for (Function *inlined_function : inlined_functions) {
        errs() << "Function " << inlined_function->getName() << " is inlined.\n";
      }

      return false;
    }
  };
}

char InlineFunctionPass::ID = 0;
static RegisterPass<InlineFunctionPass> X("inline-functions", "Print out inlined functions");

After a function has been inlined there won’t be a call any more, that’s what inlining does: it replaces the call instruction with the body of the function being called.

The only way I can think of to detect it after the fact would be looking at the debug information: if you can find an instruction claiming to be from a function with a different name from the current one then it’s probably been inlined from there.

But there may not be debug information of course, and even if there is that evidence could disappear after other transformations have happened (inlining is done to allow other simplifications and they may eliminate all instructions from simple functions in the end).

1 Like