Inserting a function call into bitcode

Hi All,

I am trying to write code for simple instrumentation. What I want to do is to insert a call to an external function for result of each conditional branch instruction. This external function simply print true or false based on the result of condition. The modified code is then written into new file. However when I try to link that file with another bitcode file (containing external function), it results “llvm-link: error loading file ‘newfile.bc’” error. This error is inconsistent. It appears for some programs and not for some other. If it links with other file, during execution it produces following error - Assertion `Addr && “Code generation didn’t add function to GlobalAddress table!”’ failed

Below is the code of my pass. It inherits ModulePass and does not have any other method except runOnModule. Am I missing something during call insertion or bitcode modification? I am using LLVM-2.6. The same code in LLVM-2.5 works correctly. (except Type::getInt32Ty, llvm-2.5 has Type::Int32Ty and no LLVMContext object)

Thanks,

Nehal

bool ConditionProfile::runOnModule(Module &M)

{

// Iterates through all functions of the module

for(Module::iterator mi = M.begin(), me = M.end(); mi!=me; mi++)

{

// Iterates through all basic blocks of the function

for(Function::iterator fi = mi->begin(), fe = mi->end(); fi!=fe; fi++)

{

BasicBlock::iterator bi = fi->end();

bi–; // Getting the terminator/last instruction of BasicBlock

if(isa(bi))

{

BranchInst *brInst = cast(bi);

// We are interested in conditional branch only

if(brInst->isUnconditional()) continue;

Value *condRes = brInst->getCondition();

errs()<<“Type:”<getType()->getDescription()<<"\n";

// Looking for a function in Module Symbol table

Constant *PrintFn = M.getOrInsertFunction("_Z12PrintCondResb", Type::getInt32Ty(context), condRes->getType(), (Type *)0);

if(!PrintFn) {

errs()<<“GetOrInsertFailed\n”;

continue;

}

std::vector<Value *> args(1);

args[0] = condRes;

// Creating a call instruction to above function.

CallInst *callInst =

CallInst::Create(PrintFn, args.begin(), args.end(), “”, bi);

callInst->setCallingConv(CallingConv::Fast);

}

}

}

// Writing modified module to new file.

std::ostream *os = new std::ofstream(“newfile.bc”);

WriteBitcodeToFile(&M, *os);

return true;

}

Hi All,

I am trying to write code for simple instrumentation. What I want to do is
to insert a call to an external function for result of each conditional
branch instruction. This external function simply print true or false based
on the result of condition. The modified code is then written into new file.
However when I try to link that file with another bitcode file (containing
external function), it results “llvm-link: error loading file 'newfile.bc'”
error. This error is inconsistent. It appears for some programs and not for
some other. If it links with other file, during execution it produces
following error - Assertion `Addr && "Code generation didn't add function
to GlobalAddress table!"' failed

Below is the code of my pass. It inherits ModulePass and does not have any
other method except runOnModule. Am I missing something during call
insertion or bitcode modification? I am using LLVM-2.6. The same code in
LLVM-2.5 works correctly. (except Type::getInt32Ty, llvm-2.5 has
Type::Int32Ty and no LLVMContext object)

Thanks,

Nehal

bool ConditionProfile::runOnModule\(Module &amp;M\)

\{

    // Iterates through all functions of the module

    for\(Module::iterator mi = M\.begin\(\), me = M\.end\(\); mi\!=me; mi\+\+\)

    \{

        // Iterates through all basic blocks of the function

        for\(Function::iterator fi = mi\-&gt;begin\(\), fe = mi\-&gt;end\(\); fi\!=fe;

fi++)

        \{

                BasicBlock::iterator bi = fi\-&gt;end\(\);

                bi\-\-;                 // Getting the terminator/last

instruction of BasicBlock

                if\(isa&lt;BranchInst&gt;\(bi\)\)

                \{

                    BranchInst \*brInst = cast&lt;BranchInst&gt;\(bi\);

                    // We are interested in conditional branch only

                    if\(brInst\-&gt;isUnconditional\(\)\) continue;

                    Value \*condRes = brInst\-&gt;getCondition\(\);

errs()<<"Type:"<<condRes->getType()->getDescription()<<"\n";

                   // Looking for a function in Module Symbol

table

                    Constant \*PrintFn =

M.getOrInsertFunction("_Z12PrintCondResb", Type::getInt32Ty(context),
condRes->getType(), (Type *)0);

                    if\(\!PrintFn\) \{

                        errs\(\)&lt;&lt;&quot;GetOrInsertFailed\\n&quot;;

                        continue;

                    \}

                    std::vector&lt;Value \*&gt; args\(1\);

                        args\[0\] = condRes;

                    // Creating a call instruction to above function\.

                    CallInst \*callInst =

                       CallInst::Create\(PrintFn, args\.begin\(\),

args.end(), "", bi);

                    callInst\-&gt;setCallingConv\(CallingConv::Fast\);

                \}

        \}

    \}

   // Writing modified module to new file\.

    std::ostream \*os = new std::ofstream\(&quot;newfile\.bc&quot;\);

    WriteBitcodeToFile\(&amp;M, \*os\);

Try putting "delete os" here?

-Eli

Why does it even have to be dynamically allocated? It looks to me like an object on the stack will do fine.

Sean

Hi Eli,

Thanks for that. Rookie mistake on my side. It solves the linking issue. However, it was not the main problem. The problem is when I execute the linked file ( modified bitcode + file containing the function), I get an assertion error - Assertion `Addr && “Code generation didn’t add function to GlobalAddress table!”’ failed.

So my main concern - is that a correct way to insert a call instruction in the bitcode the way I did? The same code for inserting a function call instruction works correctly with LLVM2.5 .

Thanks,

Nehal.

My best guess is that you're doing something wrong invoking the JIT;
there isn't anything obviously wrong with the code from your original
message.

-Eli

Have you tried running the verifier after ConditionProfile runs? Just add it to the pass manager to run right afterwards and see what it picks up.

Nick

Nehal Gandhi wrote:

Hi Eli,

Thanks for that. Rookie mistake on my side. It solves the linking issue.
However, it was not the main problem. The problem is when I execute the
linked file ( modified bitcode + file containing the function), I get an
assertion error - Assertion `Addr && "Code generation didn't add function

to

GlobalAddress table!"' failed.

So my main concern - is that a correct way to insert a call instruction

in

the bitcode the way I did? The same code for inserting a function call
instruction works correctly with LLVM2.5 .

My best guess is that you're doing something wrong invoking the JIT;
there isn't anything obviously wrong with the code from your original
message.

-Eli

Well I am just using lli to run the linked file (i.e. program.bc). The
command chain is usually as follows.

  llvm-g++ --emit-llvm -c PrintRes.cpp -o PrintRes.bc
  (PrintRes.bc has the function which I want to call from the
newfile.bc below)

  opt -load ../../../Release/lib/CondPass.so -ProfileCond < try.bc >
/dev/null
      (this generates newfile.bc while try.bc is original code)

  llvm-link -o program.bc newfile.bc PrintRes.bc
  lli program.bc

where newfile.bc is the bitcode generated by pass and PrintRes.bcis the file
that contains the function I am inserting using pass. Actually, program.bc
starts running. But when it encounters call instruction for that function,
it gives above assertion failure. The confusing thing how the same stuff
works perfectly in LLVM2.5. It is preventing me porting a quite bigger pass
(with lots of function calls and analysis part) from 2.5 to 2.6.

- Nehal.

Hi Nick

I am not quite sure what you meant by verifier. I checked online documents
and found that there is a function verifyAnalysis() in Pass but it is empty.
So do you suggest implementing that function? If it is the case, what should
I look while implementing that function? Or something else altogether?

Thanks,
Nehal.

Hmm, so the crash is in a stock lli running over program.bc? Then
your analysis pass isn't really relevant to the bug... can you attach
a crashing program.bc?

-Eli

Hi Eli,

I have attached a tar file containing Pass (ConditionPass.cpp), External
function (PrintRes.cpp) and test program (try.c). I use command chain as
describe in previous mail.

Thanks,
Nehal.

ProfileCond.tar.bz2 (1.27 KB)

Hi Eli,

I have attached a tar file containing Pass (ConditionPass.cpp), External
function (PrintRes.cpp) and test program (try.c). I use command chain as
describe in previous mail.

Can you just attach the final program.bc you pass to lli? I don't
know how to build a plugin off the top of my head.

-Eli

Here you go.

program.bc (5.05 KB)

Here you go.

There isn't anything obviously wrong with the given .bc file; output
with trunk lli:
Enter the number:10
Condition evaluated to true
Number 10 is positive

I have no idea why your version of lli is crashing.

-Eli

Nehal Gandhi wrote:

Hi Nick

I am not quite sure what you meant by verifier. I checked online documents
and found that there is a function verifyAnalysis() in Pass but it is empty.
So do you suggest implementing that function? If it is the case, what should
I look while implementing that function? Or something else altogether?

I'm assuming you have a PassManager PM, in which case it would be 'PM.add(createVerifierPass());' which is equivalent to 'opt -verify foo.bc'. Please let me know what that turns up; even if it finds no problems that fact is still useful information.

The webpage is http://llvm.org/docs/Passes.html#verify .

Nick

Nehal Gandhi wrote:

Hi Nick

I am not quite sure what you meant by verifier. I checked online documents
and found that there is a function verifyAnalysis() in Pass but it is empty.
So do you suggest implementing that function? If it is the case, what should
I look while implementing that function? Or something else altogether?

I'm assuming you have a PassManager PM, in which case it would be
'PM.add(createVerifierPass());' which is equivalent to 'opt -verify
foo.bc'. Please let me know what that turns up; even if it finds no
problems that fact is still useful information.

The webpage is http://llvm.org/docs/Passes.html#verify .

Oops, forgot to cc the whole list that I figured out the issue is
http://llvm.org/bugs/show_bug.cgi?id=5186 .

-Eli

Hi Nick,

Thanks for the link on PassManager. As Eli mentioned in one of his mails
(http://llvm.org/bugs/show_bug.cgi?id=5186), there was issue with LLVM which
was letter on resolved.

Nehal.