generating instructions with embedded ConstantExprs from within LLVM

How is this done? Everything logical I have tried has failed, here was one attempt:

Constant C = (Constant) ConstantArray::get(inst2string(I)); //fucnction defined elsewhere

//generates a correct Global string
GlobalVariable *str = new GlobalVariable(C->getType(), true,
GlobalValue::InternalLinkage,
C, mkStrName( strNumber++ ), &M);

std::vector<Value*> params; //params to a CallInst
std::vector<Value*> indices; //indices to gep
indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
Constant gep = ConstantExpr::getGetElementPtr( (Constant) str, indices);
params.push_back((Value*) gep );

CallInst *CI = new CallInst(printf, params, std::string(""), I);

This resulted in a “no such type plane” assertion. Currently I am doing this as two seperate instructions, which works, but slows down the rest of my pass.

~Patrick

How is this done? Everything logical I have tried has failed, here was
one attempt:

Can you give a few more details about what you are doing? Are you running
the verifier before writing out bytecode? Is your code operating as a
pass? Can you send a dump of the generated LLVM code?

Constant *C = (Constant*) ConstantArray::get(inst2string(I)); //fucnction defined elsewhere

One comment about this code: you don't need to have all of these casts.
In particular, above you don't need the (Constant*) cast, and you don't
need the (Value*) casts below.

//generates a correct Global string
   GlobalVariable *str = new GlobalVariable(C->getType(), true,
     GlobalValue::InternalLinkage,
      C, mkStrName( strNumber++ ), &M);

You probably don't need mkStrName here. Just use a constant name like
"debugstr" or whatever. The symbol table class will autonumber them for
you to keep them unique, and is likely to be more efficient than this
implementation.

   std::vector<Value*> params; //params to a CallInst
   std::vector<Value*> indices; //indices to gep
   indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
   indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
   Constant *gep = ConstantExpr::getGetElementPtr( (Constant*) str, indices);

This looks fine, but you can drop the casts.

   params.push_back((Value*) gep );

    CallInst *CI = new CallInst(printf, params, std::string(""), I);

You can just pass in "" here instead of std::string("") btw.

  This resulted in a "no such type plane" assertion. Currently I am
doing this as two seperate instructions, which works, but slows down the
rest of my pass.

I'm really not sure what's going on without more detail. In particular,
this assertion can happen if you attempt to write an invalid LLVM module
to bytecode. Make sure that the type of the gep value matches the first
argument to printf. If you run the verifier it should catch problems like
this (the verifier should automatically be run if you're a pass running
from opt), If the verifier doesn't catch the problem, then it's a bug in
the verifier and please let me know!

-Chris

How is this done? Everything logical I have tried has failed, here was
one attempt:

Constant *C = (Constant*) ConstantArray::get(inst2string(I)); //fucnction defined elsewhere

//generates a correct Global string
   GlobalVariable *str = new GlobalVariable(C->getType(), true,
     GlobalValue::InternalLinkage,
      C, mkStrName( strNumber++ ), &M);

...

   Constant *gep = ConstantExpr::getGetElementPtr( (Constant*) str, indices);

Sorry for responding twice. As soon as I sent that I realized the
problem. The problem is that the cast on the bottom line here is masking
the bug. In particular, you can't use the address of global variables as
constants (yet: see PR122). This is definitely a bug in LLVM that you
can't do this, but we do have a gross work-around. In particular, to get
the address of a global value as a constant, use the ConstantPointerRef
class:

Constant *strconst = ConstantPointerRef::get(str);
Constant *gep = ConstantExpr::getGetElementPtr(strconst, indices);

In the future, the GlobalValue class will derive from the Constant class,
making this unnecessary. Since the "value" of a GlobalValue is the
*address* of the global, and since this is a link-time constant, it makes
sense for it to derive from the Constant class.

Sorry for the confusion, you have every right to expect things to work
this way. In the future they will, as part of PR122. :slight_smile:

-Chris

from within LLVM

> How is this done? Everything logical I have tried has failed, here was
> one attempt:

Can you give a few more details about what you are doing? Are you running
the verifier before writing out bytecode? Is your code operating as a
pass? Can you send a dump of the generated LLVM code?

I'm running this as a pass from opt (even though it's not really an
optimization). What it does is go thourgh and find parts of code that is a
program fragment, these it converts to a format string for printf, that's
why I need the gep and the printf calls. I no longer have this version of
the code so I can't really send it :wink: Right now I am just generating two
seperate instructions, i.e.

%gep_x = getelementptr... ;<sbyte* from sbyte array>
call int %printf(sbyte* %gep_x, .....

This works fine, and aside from getting this thing to make strings for every
type of instruction it works great (note: this is a cheap hack Vikram and I
came up with, using printf's to dynamically generate code is not our final
plan :wink: )

> Constant *C = (Constant*) ConstantArray::get(inst2string(I));

//fucnction defined elsewhere

One comment about this code: you don't need to have all of these casts.
In particular, above you don't need the (Constant*) cast, and you don't
need the (Value*) casts below.

I always over-cast, it's clearer for me to read, but probably for no one
else (and static pointer casts are just noops). I'll take those out.

> //generates a correct Global string
> GlobalVariable *str = new GlobalVariable(C->getType(), true,
> GlobalValue::InternalLinkage,
> C, mkStrName( strNumber++ ), &M);

You probably don't need mkStrName here. Just use a constant name like
"debugstr" or whatever. The symbol table class will autonumber them for
you to keep them unique, and is likely to be more efficient than this
implementation.

I did not realize that, thanks :slight_smile:

> std::vector<Value*> params; //params to a CallInst
> std::vector<Value*> indices; //indices to gep
> indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
> indices.push_back((Value*) (ConstantInt::get(Type::IntTy, 0)));
> Constant *gep = ConstantExpr::getGetElementPtr( (Constant*) str,

indices);

from within LLVM

> How is this done? Everything logical I have tried has failed, here was
> one attempt:
>
> Constant *C = (Constant*) ConstantArray::get(inst2string(I));

//fucnction defined elsewhere

>
> //generates a correct Global string
> GlobalVariable *str = new GlobalVariable(C->getType(), true,
> GlobalValue::InternalLinkage,
> C, mkStrName( strNumber++ ), &M);
...
> Constant *gep = ConstantExpr::getGetElementPtr( (Constant*) str,

indices);

Sorry for responding twice. As soon as I sent that I realized the
problem. The problem is that the cast on the bottom line here is masking
the bug. In particular, you can't use the address of global variables as
constants (yet: see PR122). This is definitely a bug in LLVM that you
can't do this, but we do have a gross work-around. In particular, to get
the address of a global value as a constant, use the ConstantPointerRef
class:

Constant *strconst = ConstantPointerRef::get(str);
Constant *gep = ConstantExpr::getGetElementPtr(strconst, indices);

In the future, the GlobalValue class will derive from the Constant class,
making this unnecessary. Since the "value" of a GlobalValue is the
*address* of the global, and since this is a link-time constant, it makes
sense for it to derive from the Constant class.

Ohh thanks, I noticed that it didn't derive from Constant but I didn't see
any way around it. I should have realized that that was the problem.