First pass to settle the IDs common between disassembly styles
Second pass to display the disassembly
Divide existing MakeDXCDisassemblyString() method into helper methods to be shared
* Add helpers for creating DX op instructions with less boilerplate.
* On encode, strip any unused functions or globals to comply with strict
DXIL validation requirements.
* Create attribute sets on demand to match functions.
* Add some extra helpers for creating constants, blocks, and patching
runtime chunk.
* Pointer types implicitly referenced by objects but not directly (like global
variable or alloc/gep pointers) are not guaranteed to be present, so we need
to add them ourselves to parse correctly and identically to LLVM.
* This file format is so obtuse that it enforces a code structure almost by
design. This makes sense since it was never intended to be used anywhere
outside of LLVM internals, so it makes sense that it maps precisely to LLVM's
code structure and is hard to handle otherwise.
* This is not how LLVM does things, but sometimes DXIL blobs don't have the ptr-
to-func types present, and we always access the real function type anyway so
it should be safe to store the direct function type.
* This is a stupid requirement as the quad overdraw shader doesn't use any
interpolators, but the D3D12 runtime complains and refuses to create a PSO
unless the PS has a matching signature. This works as long as the position was
the first output from the previous stage, but if it isn't the PSO fails to
create.
* To fix this, we take the existing shader and patch it by grafting the output
signature from the last stage over onto the input signature, and patching up
where the position is.
* We also allow GetPointerType to silently return NULL when no pointer exists,
as this will be useful for encoding when we want to check if a pointer type
exists.
* We now track the values in a simple array so getting value IDs amounts to just
getting an index in this array. This avoids the need to iterate in an llvm-
identical way to enumerate values. That does mean that we need to insert new
values into the array in the correct order, which isn't too bad.
* We cheat slightly with the attributes - we combine these on load, so we lose
information about multiple groups they may reference. So we save the groups
that we read from and use that to write the attribute.
* These map more naturally to python tuples and are easier to wrap in and out.
* We also tidy up the FloatVecVal etc and standardise the members of
ShaderValue.