[un]wrapping llvm:DITypeRef

In trying to write a C binding for DIBuilder of llvm 3.6.1, I can't see a way to unwrap
llvm::DITypeRef, declared in include/llvm/IR/DebugInfo.h. This is a class with one
data member, a pointer to Metadata.

If I try to make my C type a struct with one pointer, I can't cast it to DITypeRef.
If I try to go inside the classes and use the pointer, I can cast, but can't construct
a DITypeRef when unwrapping, as both its pointer field 'Val' and the constructor are
private.

I don’t know if I’m understanding the problem exactly, so I’ll just point you to what the Go bindings are doing.

First, define wrap/unwrap for llvm::Metadata (of which DIType is a descendant):
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/IRBindings.h#L-63

Then use wrapped llvm::Metadata in the C API:
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/DIBuilderBindings.h

(You could have DIType-specific wrap/unwrap too, using the same method.)

HTH,
Andrew

    In trying to write a C binding for DIBuilder of llvm 3.6.1, I can't see a way to unwrap
    llvm::DITypeRef, declared in include/llvm/IR/DebugInfo.h. This is a class with one
    data member, a pointer to Metadata.

    If I try to make my C type a struct with one pointer, I can't cast it to DITypeRef.
    If I try to go inside the classes and use the pointer, I can cast, but can't construct
    a DITypeRef when unwrapping, as both its pointer field 'Val' and the constructor are
    private.

I don't know if I'm understanding the problem exactly, so I'll just point you to what the Go bindings are doing.

First, define wrap/unwrap for llvm::Metadata (of which DIType is a descendant):
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/IRBindings.h#L-63

Then use wrapped llvm::Metadata in the C API:
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/DIBuilderBindings.h

(You could have DIType-specific wrap/unwrap too, using the same method.)

My problem is not DIType, it's DITypeRef. This was added sometime after 3.4.2 and
by 3.6.1. It is used, e.g. for formal parameter Ty of DIBuilder::createLocalVariable.
These Go bindings apparently have not been updated to 3.6.1, as they give DIType in
such places.

However, in looking more carefully at DIType, with the intention of being able to better
explain why DITypeRef gives me a problem that DIType does not, I find the way I need
to construct a DITypeRef is actually declared in DIType:

class DIType : public DIScope {
  ...
  public:
   ...
   operator DITypeRef () const {
   ^^^^^^^^^^^^^^^^^^
     assert(isType() &&
            "constructing DITypeRef from an MDNode that is not a type");
     return DITypeRef(&*getRef());
   }

This, through a series of specializations, befriendings, etc., is able to
get to the private constructor of DITypeRef.

This should help solve my problem, once I figure out how to construct a
properly equivalent DIType.

Thanks.

    In trying to write a C binding for DIBuilder of llvm 3.6.1, I can't see a way to unwrap
    llvm::DITypeRef, declared in include/llvm/IR/DebugInfo.h. This is a class with one
    data member, a pointer to Metadata.

    If I try to make my C type a struct with one pointer, I can't cast it to DITypeRef.
    If I try to go inside the classes and use the pointer, I can cast, but can't construct
    a DITypeRef when unwrapping, as both its pointer field 'Val' and the constructor are
    private.

I don't know if I'm understanding the problem exactly, so I'll just point you to what the Go bindings are doing.

First, define wrap/unwrap for llvm::Metadata (of which DIType is a descendant):
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/IRBindings.h#L-63

Then use wrapped llvm::Metadata in the C API:
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/DIBuilderBindings.h

(You could have DIType-specific wrap/unwrap too, using the same method.)

My problem is not DIType, it's DITypeRef. This was added sometime after 3.4.2 and
by 3.6.1. It is used, e.g. for formal parameter Ty of DIBuilder::createLocalVariable.
These Go bindings apparently have not been updated to 3.6.1, as they give DIType in
such places.

However, in looking more carefully at DIType, with the intention of being able to better
explain why DITypeRef gives me a problem that DIType does not, I find the way I need
to construct a DITypeRef is actually declared in DIType:

class DIType : public DIScope {
  ...
  public:
   ...
   operator DITypeRef () const {
   ^^^^^^^^^^^^^^^^^^
     assert(isType() &&
            "constructing DITypeRef from an MDNode that is not a type");
     return DITypeRef(&*getRef());
   }

This, through a series of specializations, befriendings, etc., is able to
get to the private constructor of DITypeRef.

This should help solve my problem, once I figure out how to construct a
properly equivalent DIType.

I was mistaken. This does not solve my problem. The implicit conversion
operator DITypeRef converts from a DIType, which can contain only an MDNode*,
but I need to construct a DITypeRef, which can contain a Metadata*. The
constructor I need is here:

template <typename T> class DIRef {
   template <typename DescTy>
   friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
   friend DIScopeRef DIScope::getContext() const;
   friend DIScopeRef DIScope::getRef() const;
   friend class DIType;

   /// \brief Val can be either a MDNode or a MDString.
   ///
   /// In the latter, MDString specifies the type identifier.
   const Metadata *Val;
   explicit DIRef(const Metadata *V);
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

but it is private. I am trying very hard to avoid in-llvm-tree modifications
(we've been down that path with a gcc-derived back end.) Do I have any alternative?
Would the project accept making this constructor public?

    In trying to write a C binding for DIBuilder of llvm 3.6.1, I can't
see a way to unwrap
    llvm::DITypeRef, declared in include/llvm/IR/DebugInfo.h. This is a
class with one
    data member, a pointer to Metadata.

    If I try to make my C type a struct with one pointer, I can't cast
it to DITypeRef.
    If I try to go inside the classes and use the pointer, I can cast,
but can't construct
    a DITypeRef when unwrapping, as both its pointer field 'Val' and the
constructor are
    private.

I don't know if I'm understanding the problem exactly, so I'll just
point you to what the Go bindings are doing.

First, define wrap/unwrap for llvm::Metadata (of which DIType is a
descendant):
http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/IRBindings.h#L-63

Then use wrapped llvm::Metadata in the C API:

http://llvm.org/klaus/llvm/blob/master/bindings/go/llvm/DIBuilderBindings.h

(You could have DIType-specific wrap/unwrap too, using the same method.)

My problem is not DIType, it's DITypeRef. This was added sometime after
3.4.2 and
by 3.6.1. It is used, e.g. for formal parameter Ty of
DIBuilder::createLocalVariable.
These Go bindings apparently have not been updated to 3.6.1, as they give
DIType in
such places.

However, in looking more carefully at DIType, with the intention of being
able to better
explain why DITypeRef gives me a problem that DIType does not, I find the
way I need
to construct a DITypeRef is actually declared in DIType:

class DIType : public DIScope {
  ...
  public:
   ...
   operator DITypeRef () const {
   ^^^^^^^^^^^^^^^^^^
     assert(isType() &&
            "constructing DITypeRef from an MDNode that is not a type");
     return DITypeRef(&*getRef());
   }

This, through a series of specializations, befriendings, etc., is able to
get to the private constructor of DITypeRef.

This should help solve my problem, once I figure out how to construct a
properly equivalent DIType.

I was mistaken. This does not solve my problem. The implicit conversion
operator DITypeRef converts from a DIType, which can contain only an
MDNode*,
but I need to construct a DITypeRef, which can contain a Metadata*. The
constructor I need is here:

template <typename T> class DIRef {
  template <typename DescTy>
  friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
  friend DIScopeRef DIScope::getContext() const;
  friend DIScopeRef DIScope::getRef() const;
  friend class DIType;

  /// \brief Val can be either a MDNode or a MDString.
  ///
  /// In the latter, MDString specifies the type identifier.
  const Metadata *Val;
  explicit DIRef(const Metadata *V);
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

but it is private. I am trying very hard to avoid in-llvm-tree
modifications
(we've been down that path with a gcc-derived back end.) Do I have any
alternative?
Would the project accept making this constructor public?

Have you found where it's called from yet? (perhaps by putting an
"assert(false)" or defining it as deleted ("= delete") and
recompiling/running tests) Then see about using the same mechanism for your
use case?

This was probably an oversight. Frankly, I'm not sure DITypeRef should
really be in the DIBuilder API -- frontends should probably just pass
in a DIType.

Note that in ToT, DITypeRef has completely changed; it's a typedef from
`TypedDINodeRef<DIType>` and has a public constructor from `Metadata*`.

I suggest you just make the constructor public in your local copy of
LLVM; even better, work off of the LLVM 3.7 branch (better still, work
off of ToT).

Thanks, that helps.