[RFC] Better support for typed pointers in an opaque pointer world

Sorry for my silence on the topic as of late, but I’ve been hard at work pushing opaque pointers into the SPIR-V translator without any of these features. (FWIW, with my local patches in play, I’m up to about a 90% pass rate on some internal test suites.)

So, some updates:

To make this possible the DirectX backend has a DXILPointerType which is a subclass of llvm::Type so that it can be used to generate FunctionType objects and other objects that depend on encompassed types.

I think the simplest way to get this done is to move DXILPointerType to TypedPointerType. To satisfy Nikita’s concern about this leaking into IR, I suspect it’s sufficient to drop an assertion that the type isn’t a typed pointer type in the Value constructor. There are a couple of times where I think it might be helpful to have a Value with a TypedPointerType temporarily, but I’ve already written the code necessary to deal with std::pair<Value, MyTypedPointerType>, so it’s only very minor ergonomic concerns.

Using elementtype attribute as described in the original RFC.

The primary alternative to getting this information is to use the Itanium demangler to figure out what the element types should have been, which others have suggested. I have found two issues with this approach:

  1. Not every function is guaranteed to have a mangled name–in particular, the main kernel function itself will probably not have a mangled name (although I suspect the main kernel function is the one where the bitcast approach is least likely to be damaging, at least should opaque types be sorted out). I’m fine relying on a demangling approach to get the SPIR-V builtins correctly sorted out, but I’m wary of doing so for all user kernels.
  2. As it turns out, the key opaque types for SPIR-V currently have several different naming conventions. Whereas the translator originally handled these by simply changing the names of the LLVM struct types themselves, getting this working when you’re recovering struct names from the mangled name is more challenging.

At this point, my working thesis is that moving to the opaque type representation will provide a sufficient solution to these problems, but I only just got started on prototyping that work last night, so I can’t give any strong guarantees.

From a purely technical perspective, I can’t see this happening before September.

September is 5 weeks away, that’s not actually a lot of time :wink:. I think SPIR-V will need the opaque type added, and a new LLVM ABI for SPIR-V decided, before typed pointers can be removed. Without that stuff, we’d be at a state where only some stuff (perhaps most stuff, but definitely not all stuff) works with opaque pointers.

One issue I see with this approach is that this will break binary compatibility for SPIR-V as it currently produces the pointer types fully in the signature. This implies that after such change we can no longer link SPIR-V files compiled with previous Clang releases. Another limitation is that this might prevent mixing SPIR-V modules with those compiled from non-clang based tools as they might prefer to continue preserving pointer types in the signature. Overall, it would be nicer if we could just recover the signature of functions to the form it was generated before.

It may be possible to preserve this information if we change the LLVM ABI for SPIR-V. I think it makes sense to hold off on changing this ABI until after LLVM 15 is branched, given that I can’t guarantee that the opaque type stuff would land before LLVM 15.