[LLVMdev] How to place call(s) to functions found in other llvm modules ???

Mian M. Hamayun mian-muhammad.hamayun at imag.fr
Wed Aug 31 10:00:25 PDT 2011


Hello Everyone,

I am trying to create two modules in LLVM, where first module contains 
the definition of a function, gcd in this example and another module 
contains a call to this function. My example is based on the following 
tutorial, with a few changes.
http://llvm.org/releases/2.6/docs/tutorial/JITTutorial2.html

When I execute the verifier pass on my modules, it complains that the 
'GCDMain' module is malformed and aborts when I try to write this module 
as a bitcode file.

Here is the output of my example.

----------------------------------------------------------------------
Referencing function in another module!
   %tmp = call i32 @gcd(i32 30, i32 50)
Instruction does not dominate all uses!
   %tmp = call i32 @gcd(i32 30, i32 50)
   ret i32 %tmp
Broken module found, verification continues.
Referencing function in another module!
   %tmp = call i32 @gcd(i32 30, i32 50)
Instruction does not dominate all uses!
   %tmp = call i32 @gcd(i32 30, i32 50)
   ret i32 %tmp
Broken module found, verification continues.
Broken module found, verification continues.
; ModuleID = 'GCD'

define i32 @gcd(i32 %x, i32 %y) {
entry:
   %tmp = icmp eq i32 %x, %y
   br i1 %tmp, label %return, label %cond_false

return:                                           ; preds = %entry
   ret i32 %x

cond_false:                                       ; preds = %entry
   %tmp2 = icmp ult i32 %x, %y
   br i1 %tmp2, label %cond_true, label %cond_false1

cond_true:                                        ; preds = %cond_false
   %tmp3 = sub i32 %y, %x
   %tmp4 = call i32 @gcd(i32 %x, i32 %tmp3)
   ret i32 %tmp4

cond_false1:                                      ; preds = %cond_false
   %tmp5 = sub i32 %x, %y
   %tmp6 = call i32 @gcd(i32 %tmp5, i32 %y)
   ret i32 %tmp6
}
; ModuleID = 'GCDMain'

define i32 @main() {
EntryBlock:
   %tmp = call i32 @gcd(i32 30, i32 50)
   ret i32 %tmp
}
ModuleMaker2: 
/home/hamayun/workspace/NaSiK/sw/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp:155: 
unsigned int llvm::ValueEnumerator::getValueID(const llvm::Value*) 
const: Assertion `I != ValueMap.end() && "Value not in slotcalculator!"' 
failed.
Aborted
----------------------------------------------------------------------

And here is the source code of my example.

----------------------------------------------------------------------
Module* makeLLVMModule(LLVMContext& Context);
Module* makeMainModule(LLVMContext& Context, Module &inMod);

static tool_output_file *GetOutputStream(const char *FileName)
{
   std::string error;

   tool_output_file *FDOut = new tool_output_file(FileName, error, 
raw_fd_ostream::F_Binary);
   if (!error.empty()) {
     errs() << error << '\n';
     delete FDOut;
     return 0;
   }

   return FDOut;
}

int main(int argc, char**argv) {
   LLVMContext& Context = getGlobalContext();

   Module* ModGCD  = makeLLVMModule(Context);
   Module* ModMain = makeMainModule(Context, *ModGCD);

   OwningPtr<tool_output_file> OutGCD (GetOutputStream("gcd.bc"));
   if (!OutGCD) return 1;

   OwningPtr<tool_output_file> OutMain (GetOutputStream("maingcd.bc"));
   if (!OutMain) return 1;

   verifyModule(*ModGCD, PrintMessageAction);
   verifyModule(*ModMain, PrintMessageAction);

   PassManager PM;
   PM.add(createPrintModulePass(&outs()));
   PM.run(*ModGCD);
   PM.run(*ModMain);

   WriteBitcodeToFile(ModGCD, OutGCD->os());
   WriteBitcodeToFile(ModMain, OutMain->os());

   OutGCD->keep();
   OutMain->keep();

   delete ModGCD;
   delete ModMain;
   return 0;
}

Module* makeMainModule(LLVMContext& Context, Module &inMod)
{
   // Module Construction
   Module* mod = new Module("GCDMain", Context);

   FunctionType *FT = FunctionType::get(Type::getInt32Ty(Context), 
std::vector<const llvm::Type*, std::allocator<const llvm::Type*> >
                                       (2, Type::getInt32Ty(Context)), 
/*not vararg*/false);

   Constant* c = inMod.getOrInsertFunction("gcd", FT);
   Function* gcd = cast<Function>(c);

   FunctionType *FT_Main = FunctionType::get(Type::getInt32Ty(Context), 
/*not vararg*/false);
   Function *F_Main = Function::Create(FT_Main, 
Function::ExternalLinkage, "main", mod);

   BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", F_Main);
   IRBuilder<> builder(BB);

   Value *Thirty = ConstantInt::get(Type::getInt32Ty(Context), 30);
   Value *Fifty  = ConstantInt::get(Type::getInt32Ty(Context), 50);
   std::vector<Value*> args;
   args.push_back(Thirty);
   args.push_back(Fifty);
   Value *gcd_val = builder.CreateCall(gcd, args.begin(), args.end(), 
"tmp");

   builder.CreateRet(gcd_val);
   return mod;
}

Module* makeLLVMModule(LLVMContext& Context) {
   // Module Construction
   Module* mod = new Module("GCD", Context);

   FunctionType *FT = FunctionType::get(Type::getInt32Ty(Context), 
std::vector<const llvm::Type*, std::allocator<const llvm::Type*> >
                                       (2, Type::getInt32Ty(Context)), 
/*not vararg*/false);

   Constant* c = mod->getOrInsertFunction("gcd", FT);
   Function* gcd = cast<Function>(c);
   gcd->setLinkage(Function::ExternalLinkage);
   gcd->setCallingConv(CallingConv::C);

   Function::arg_iterator args = gcd->arg_begin();
   Value* x = args++;
   x->setName("x");
   Value* y = args++;
   y->setName("y");

   BasicBlock* entry = BasicBlock::Create(Context, "entry", gcd);
   BasicBlock* ret = BasicBlock::Create(Context, "return", gcd);
   BasicBlock* cond_false = BasicBlock::Create(Context, "cond_false", gcd);
   BasicBlock* cond_true = BasicBlock::Create(Context, "cond_true", gcd);
   BasicBlock* cond_false_2 = BasicBlock::Create(Context, "cond_false", 
gcd);

   IRBuilder<> builder(entry);
   Value* xEqualsY = builder.CreateICmpEQ(x, y, "tmp");
   builder.CreateCondBr(xEqualsY, ret, cond_false);

   builder.SetInsertPoint(ret);
   builder.CreateRet(x);

   builder.SetInsertPoint(cond_false);
   Value* xLessThanY = builder.CreateICmpULT(x, y, "tmp");
   builder.CreateCondBr(xLessThanY, cond_true, cond_false_2);

   builder.SetInsertPoint(cond_true);
   Value* yMinusX = builder.CreateSub(y, x, "tmp");
   std::vector<Value*> args1;
   args1.push_back(x);
   args1.push_back(yMinusX);
   Value* recur_1 = builder.CreateCall(gcd, args1.begin(), args1.end(), 
"tmp");
   builder.CreateRet(recur_1);

   builder.SetInsertPoint(cond_false_2);
   Value* xMinusY = builder.CreateSub(x, y, "tmp");
   std::vector<Value*> args2;
   args2.push_back(xMinusY);
   args2.push_back(y);
   Value* recur_2 = builder.CreateCall(gcd, args2.begin(), args2.end(), 
"tmp");
   builder.CreateRet(recur_2);

   return mod;
}

----------------------------------------------------------------------

I am not sure why its happening or what I am missing ... :(
I also tried to search on this topic, but couldn't find similar posts 
anywhere.

Any pointers / suggestions will be highly appreciated.

Thanks in advance.

-- 
Hamayun

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3781 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110831/6f4d188c/attachment.bin>


More information about the llvm-dev mailing list