C++ CreateConstGEP questions

There are two C++ signatures for CreateConstGEP1_32:

    Value * CreateConstGEP1_32 (Value *Ptr, unsigned Idx0, const Twine &Name="")
    Value * CreateConstGEP1_32 (Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")

I'm assuming that this means that the caller can supply the expected type, and get error checking or casting? Or choose to not supply the type and get whatever they get?

But for CreateConstGEP2_32, there is only the variety with the type supplied:

    Value * CreateConstGEP2_32 (Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")

For CreateConstGEP2_64, there is only the version with no Type supplied:

    Value * CreateConstGEP2_64 (Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")

Same for CreateConstGEP1_64 -- no Type* parameter.

Can anybody offer insight into the strange lack of symmetry here? Why does GEP2_32 require the type, but GEP1_64 and GEP2_64 doesn't allow it all, but GEP1_32 has both varieties?

Is it always safe to pass nullptr as the type?

Also, if you know your constant indices fit into 32 bits, is there any advantage to calling the _32 versions over the _64?

This is likely fallout from the in-progress typeless pointer work. The goal is to remove the pointee type from the pointer, so i8*, i64*, %foo* and so on will all simply be ptr (optionally qualified with an address space). As an intermediate step to this, GEPs now must be associated with the pointee type because eventually that information will no longer be available from the type.

If you want your code to be easy to migrate to future LLVM versions, please use the version that takes an explicit type parameter and provide the type (by some mechanism other than pointee->getType()). In the short term, you will get some type checking (an assertion failure if the types don’t match). Eventually, this will be the only API.

I suspect that the _64 versions were simply missed in the patch and the _32 versions without the type parameter were not GC’d to provide a smoother migration path. They should ideally be marked with a deprecated attribute, as they are going to stop working (and become impossible to implement) at some point.

Passing nullptr here ought to trigger an assertion failure, so probably not a sensible thing to do.


Thanks David - that about sums it up.

I think my choice of GEP migration wasn’t the best - leaving both versions in and/or removing the old version but allowing null to be passed as a silent fallback. In other cases I’ve been more rigorous about just changing the API to require the extra type information (& making callers just getPointeeType as an immediate solution, then pushing those calls up a layer, etc, until I could get rid of them entirely). That made the transition boundary clearer.

  • David