Bogus assert in VMCore/Instructions.cpp CallInst::Create?

Evening,

I was writing some code that tried to insert calls to the
llvm.annotation intrinsic function, which has a signature of (i32,
i8*, i8*, i32). The code is below.

void addAnnotation( BasicBlock *block, Function *F)
{
    string foo = "foo";
    string bar = "barr";

    Type *charTy = Type::getInt8Ty(block->getContext());

    ArrayType *s1Ty = ArrayType::get(charTy, foo.size()+1);
    ArrayType *s2Ty = ArrayType::get(charTy, bar.size()+1);

    Constant *ar1 = ConstantArray::get(block->getContext(), foo);
    Constant *ar2 = ConstantArray::get(block->getContext(), bar);

    GlobalVariable *g1 = NULL;
    GlobalVariable *g2 = NULL;

    g1 = new GlobalVariable( *F->getParent(),
                                    s1Ty,
                                    true,
                                    GlobalValue::PrivateLinkage,
                                    0,
                                    "");
    g1->setAlignment(1);

    g2 = new GlobalVariable( *F->getParent(),
                                    s2Ty,
                                    true,
                                    GlobalValue::PrivateLinkage,
                                    0,
                                    "");
    g2->setAlignment(1);

    vector<Constant*> s1_id;
    vector<Constant*> s2_id;
    s1_id.push_back(ConstantInt::get( block->getContext(),
                                        APInt(64, StringRef("0"), 10)));
    s1_id.push_back(ConstantInt::get( block->getContext(),
                                        APInt(64, StringRef("0"), 10)));

    s2_id.push_back(ConstantInt::get( block->getContext(),
                                        APInt(64, StringRef("0"), 10)));
    s2_id.push_back(ConstantInt::get( block->getContext(),
                                        APInt(64, StringRef("0"), 10)));

    g1->setInitializer(ar1);
    g2->setInitializer(ar2);

    Type *tys = { Type::getInt32Ty(block->getContext()) };
    Function *annot = Intrinsic::getDeclaration( F->getParent(),
                                                    Intrinsic::annotation,
                                                    tys);
    Value *v1 =ConstantExpr::getGetElementPtr(g1, s1_id);
    Value *v2 =ConstantExpr::getGetElementPtr(g2, s2_id);
    Value *c1 = ConstantInt::get(tys, 1);
    Value *c2 = ConstantInt::get(tys, 0);

    vector<Value*> v;
    v.push_back(c1);
    v.push_back(v1);
    v.push_back(v2);
    v.push_back(c2);

    Value *callAnnot = CallInst::Create(annot, v, "", block);

    return;
}

When I try and create the CallInst, an assert in
VMCore/Instructions.cpp fails, saying that the type of second
parameter of the function signature (i8*) does not match the type of
the first argument (which is also i8*).

I can, in the addAnontation function, call dump() on both the second
parameter of the llvm.annotate function and the second element of the
'v' array, and they are indeed both i8*. I wasn't able to find an
operator== method for Type, and it seems that the pointer values are
different between the value populated / created by
ConstantExpr::getGetElementPtr and Intrinsic::getDeclaration.

For the moment, I commented out the check in VMCore/Instructions.cpp.
Could I add an operator== to Type that compares the TypeIDs? or am I
suffering from a fundamental misunderstanding?

Thank you,

Andrew

Andrew Ruef wrote:

Evening,

I was writing some code that tried to insert calls to the
llvm.annotation intrinsic function, which has a signature of (i32,
i8*, i8*, i32). The code is below.

void addAnnotation( BasicBlock *block, Function *F)
{
     string foo = "foo";
     string bar = "barr";

     Type *charTy = Type::getInt8Ty(block->getContext());

     ArrayType *s1Ty = ArrayType::get(charTy, foo.size()+1);
     ArrayType *s2Ty = ArrayType::get(charTy, bar.size()+1);

     Constant *ar1 = ConstantArray::get(block->getContext(), foo);
     Constant *ar2 = ConstantArray::get(block->getContext(), bar);

     GlobalVariable *g1 = NULL;
     GlobalVariable *g2 = NULL;

     g1 = new GlobalVariable( *F->getParent(),
                                     s1Ty,
                                     true,
                                     GlobalValue::PrivateLinkage,
                                     0,
                                     "");
     g1->setAlignment(1);

     g2 = new GlobalVariable( *F->getParent(),
                                     s2Ty,
                                     true,
                                     GlobalValue::PrivateLinkage,
                                     0,
                                     "");
     g2->setAlignment(1);

     vector<Constant*> s1_id;
     vector<Constant*> s2_id;
     s1_id.push_back(ConstantInt::get( block->getContext(),
                                         APInt(64, StringRef("0"), 10)));
     s1_id.push_back(ConstantInt::get( block->getContext(),
                                         APInt(64, StringRef("0"), 10)));

     s2_id.push_back(ConstantInt::get( block->getContext(),
                                         APInt(64, StringRef("0"), 10)));
     s2_id.push_back(ConstantInt::get( block->getContext(),
                                         APInt(64, StringRef("0"), 10)));

     g1->setInitializer(ar1);
     g2->setInitializer(ar2);

     Type *tys = { Type::getInt32Ty(block->getContext()) };
     Function *annot = Intrinsic::getDeclaration( F->getParent(),
                                                     Intrinsic::annotation,
                                                     tys);
     Value *v1 =ConstantExpr::getGetElementPtr(g1, s1_id);
     Value *v2 =ConstantExpr::getGetElementPtr(g2, s2_id);
     Value *c1 = ConstantInt::get(tys, 1);
     Value *c2 = ConstantInt::get(tys, 0);

     vector<Value*> v;
     v.push_back(c1);
     v.push_back(v1);
     v.push_back(v2);
     v.push_back(c2);

     Value *callAnnot = CallInst::Create(annot, v, "", block);

     return;
}

When I try and create the CallInst, an assert in
VMCore/Instructions.cpp fails, saying that the type of second
parameter of the function signature (i8*) does not match the type of
the first argument (which is also i8*).

I can, in the addAnontation function, call dump() on both the second
parameter of the llvm.annotate function and the second element of the
'v' array, and they are indeed both i8*. I wasn't able to find an
operator== method for Type, and it seems that the pointer values are
different between the value populated / created by
ConstantExpr::getGetElementPtr and Intrinsic::getDeclaration.

For the moment, I commented out the check in VMCore/Instructions.cpp.
Could I add an operator== to Type that compares the TypeIDs? or am I
suffering from a fundamental misunderstanding?

Types are indeed pointer comparable. If you have two Type*'s which print the same type but have different addresses then they belong to different LLVMContexts.

Over IRC, you mentioned that the block and function have the same context, but the module has a different one. Because the intrinsic is being created with the module's context, it won't match. Of course, functions must be created with the context of the module that owns them, the bug is there.

Nick

This was the problem! The module had been created under one context
and due to a bug elsewhere in my program, everything else was using a
different context! Once changed, the system works.

Thank you very much.