[LLVMdev] Tarjan+function_ptrs == trouble ?

Chris Lattner sabre at nondot.org
Fri Dec 6 00:51:01 PST 2002


> if you take the time to print out the function each non-looping node iter
> traverses, it never reaches main...

Ok, first note that the CallGraph class does really stupid (but correct)
things for function pointers, so you're not going to see anything
remarkably nice here... Make sure to read the CallGraph.h comments to
understand exactly what is going on.

Despite that, I can verify that the SCC iterator seems to not be doing the
right thing.  On the testcase (below), and with the pass below, I get the
following:

$ opt -load /localhome/lattner/llvm/lib/Debug/libtest.so -test < test.o > /dev/null
New SCC
  Node: __main
New SCC
  Node: func_one
New SCC
  Node: func_two
New SCC
  Node: func_three

Which doesn't visit main.  Vikram, could you look into this if you get a
chance?

-Chris

------------------- Pass code ----------------------------

#include "llvm/Analysis/CallGraph.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "Support/TarjanSCCIterator.h"

struct Test : public Pass {
  virtual bool run(Module &F) {
    typedef TarjanSCC_iterator<CallGraph*> MyTarjan;
    CallGraph& callGraph = getAnalysis<CallGraph>();
    for (MyTarjan I = tarj_begin(&callGraph), E = tarj_end(&callGraph); I != E; ++I) {
      SCC<CallGraph*> *S = *I;
      assert(S);
      std::cerr << "New SCC\n";
      for (unsigned i = 0, e = S->size(); i != e; ++i)
        if (Function *F = (*S)[i]->getFunction())
          std::cerr << "  Node: " << F->getName() << "\n";
        else
          std::cerr << "  Indirect node\n";
    }
    return false;
  }
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
    AU.addRequired<CallGraph>();
  };
};
RegisterOpt<Test> Z("test", "test");


-------------------- Testcase ------------------------

#include <stdlib.h>
#include <stdio.h>

//#define WORKS

int * a_global;

int a_predicate = 1;
int another_pred =0;

int func_one()
{
    return 1;
}

int func_two()
{
    return 2;
}

int func_three()
{
    return 3;
}

int main()
{
    int (*func_ptr)();

    if(a_predicate)
        func_ptr = func_one;
    else if(another_pred)
        func_ptr = func_two;
    else
        func_ptr = func_three;

#ifdef WORKS
    return func_one();
#else
    return func_ptr();
#endif
}





More information about the llvm-dev mailing list