xref: /llvm-project/llvm/lib/MC/DXContainerPSVInfo.cpp (revision c62c74639ad6eb0988861077b7123fa2b2c17cc5)
1ad93908eSChris Bieneman //===- llvm/MC/DXContainerPSVInfo.cpp - DXContainer PSVInfo -----*- C++ -*-===//
2ad93908eSChris Bieneman //
3ad93908eSChris Bieneman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ad93908eSChris Bieneman // See https://llvm.org/LICENSE.txt for license information.
5ad93908eSChris Bieneman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ad93908eSChris Bieneman //
7ad93908eSChris Bieneman //===----------------------------------------------------------------------===//
8ad93908eSChris Bieneman 
9ad93908eSChris Bieneman #include "llvm/MC/DXContainerPSVInfo.h"
10ad93908eSChris Bieneman #include "llvm/BinaryFormat/DXContainer.h"
110c3f51c0SChris Bieneman #include "llvm/MC/StringTableBuilder.h"
12b46d0353SChris Bieneman #include "llvm/Support/EndianStream.h"
13ad93908eSChris Bieneman #include "llvm/Support/raw_ostream.h"
14ad93908eSChris Bieneman 
15ad93908eSChris Bieneman using namespace llvm;
16ad93908eSChris Bieneman using namespace llvm::mcdxbc;
17dd3f7b02SChris Bieneman using namespace llvm::dxbc::PSV;
18ad93908eSChris Bieneman 
190c3f51c0SChris Bieneman static constexpr size_t npos = StringRef::npos;
200c3f51c0SChris Bieneman 
FindSequence(ArrayRef<uint32_t> Buffer,ArrayRef<uint32_t> Sequence)210c3f51c0SChris Bieneman static size_t FindSequence(ArrayRef<uint32_t> Buffer,
220c3f51c0SChris Bieneman                            ArrayRef<uint32_t> Sequence) {
230c3f51c0SChris Bieneman   if (Buffer.size() < Sequence.size())
240c3f51c0SChris Bieneman     return npos;
250c3f51c0SChris Bieneman   for (size_t Idx = 0; Idx <= Buffer.size() - Sequence.size(); ++Idx) {
260c3f51c0SChris Bieneman     if (0 == memcmp(static_cast<const void *>(&Buffer[Idx]),
270c3f51c0SChris Bieneman                     static_cast<const void *>(Sequence.begin()),
280c3f51c0SChris Bieneman                     Sequence.size() * sizeof(uint32_t)))
290c3f51c0SChris Bieneman       return Idx;
300c3f51c0SChris Bieneman   }
310c3f51c0SChris Bieneman   return npos;
320c3f51c0SChris Bieneman }
330c3f51c0SChris Bieneman 
340c3f51c0SChris Bieneman static void
ProcessElementList(StringTableBuilder & StrTabBuilder,SmallVectorImpl<uint32_t> & IndexBuffer,SmallVectorImpl<v0::SignatureElement> & FinalElements,SmallVectorImpl<StringRef> & SemanticNames,ArrayRef<PSVSignatureElement> Elements)350c3f51c0SChris Bieneman ProcessElementList(StringTableBuilder &StrTabBuilder,
360c3f51c0SChris Bieneman                    SmallVectorImpl<uint32_t> &IndexBuffer,
370c3f51c0SChris Bieneman                    SmallVectorImpl<v0::SignatureElement> &FinalElements,
380c3f51c0SChris Bieneman                    SmallVectorImpl<StringRef> &SemanticNames,
390c3f51c0SChris Bieneman                    ArrayRef<PSVSignatureElement> Elements) {
400c3f51c0SChris Bieneman   for (const auto &El : Elements) {
410c3f51c0SChris Bieneman     // Put the name in the string table and the name list.
420c3f51c0SChris Bieneman     StrTabBuilder.add(El.Name);
430c3f51c0SChris Bieneman     SemanticNames.push_back(El.Name);
440c3f51c0SChris Bieneman 
450c3f51c0SChris Bieneman     v0::SignatureElement FinalElement;
460c3f51c0SChris Bieneman     memset(&FinalElement, 0, sizeof(v0::SignatureElement));
470c3f51c0SChris Bieneman     FinalElement.Rows = static_cast<uint8_t>(El.Indices.size());
480c3f51c0SChris Bieneman     FinalElement.StartRow = El.StartRow;
490c3f51c0SChris Bieneman     FinalElement.Cols = El.Cols;
500c3f51c0SChris Bieneman     FinalElement.StartCol = El.StartCol;
510c3f51c0SChris Bieneman     FinalElement.Allocated = El.Allocated;
520c3f51c0SChris Bieneman     FinalElement.Kind = El.Kind;
530c3f51c0SChris Bieneman     FinalElement.Type = El.Type;
540c3f51c0SChris Bieneman     FinalElement.Mode = El.Mode;
550c3f51c0SChris Bieneman     FinalElement.DynamicMask = El.DynamicMask;
560c3f51c0SChris Bieneman     FinalElement.Stream = El.Stream;
570c3f51c0SChris Bieneman 
580c3f51c0SChris Bieneman     size_t Idx = FindSequence(IndexBuffer, El.Indices);
590c3f51c0SChris Bieneman     if (Idx == npos) {
600c3f51c0SChris Bieneman       FinalElement.IndicesOffset = static_cast<uint32_t>(IndexBuffer.size());
610c3f51c0SChris Bieneman       IndexBuffer.insert(IndexBuffer.end(), El.Indices.begin(),
620c3f51c0SChris Bieneman                          El.Indices.end());
630c3f51c0SChris Bieneman     } else
640c3f51c0SChris Bieneman       FinalElement.IndicesOffset = static_cast<uint32_t>(Idx);
650c3f51c0SChris Bieneman     FinalElements.push_back(FinalElement);
660c3f51c0SChris Bieneman   }
670c3f51c0SChris Bieneman }
680c3f51c0SChris Bieneman 
write(raw_ostream & OS,uint32_t Version) const69ad93908eSChris Bieneman void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
700c3f51c0SChris Bieneman   assert(IsFinalized && "finalize must be called before write");
710c3f51c0SChris Bieneman 
72ad93908eSChris Bieneman   uint32_t InfoSize;
735fdf8605SChris Bieneman   uint32_t BindingSize;
74ad93908eSChris Bieneman   switch (Version) {
75ad93908eSChris Bieneman   case 0:
76ad93908eSChris Bieneman     InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo);
775fdf8605SChris Bieneman     BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
78ad93908eSChris Bieneman     break;
79ad93908eSChris Bieneman   case 1:
80ad93908eSChris Bieneman     InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo);
815fdf8605SChris Bieneman     BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
82ad93908eSChris Bieneman     break;
83ad93908eSChris Bieneman   case 2:
84ad93908eSChris Bieneman     InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);
855fdf8605SChris Bieneman     BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
86*c62c7463SCooper Partin     break;
87*c62c7463SCooper Partin   case 3:
88*c62c7463SCooper Partin   default:
89*c62c7463SCooper Partin     InfoSize = sizeof(dxbc::PSV::v3::RuntimeInfo);
90*c62c7463SCooper Partin     BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
91ad93908eSChris Bieneman   }
92cde54df3SCooper Partin 
93*c62c7463SCooper Partin   // Write the size of the info.
941538b82fSCooper Partin   support::endian::write(OS, InfoSize, llvm::endianness::little);
95*c62c7463SCooper Partin 
96ad93908eSChris Bieneman   // Write the info itself.
97ad93908eSChris Bieneman   OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);
98dd3f7b02SChris Bieneman 
99dd3f7b02SChris Bieneman   uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());
100dd3f7b02SChris Bieneman 
1014a0ccfa8SKazu Hirata   support::endian::write(OS, ResourceCount, llvm::endianness::little);
1020c3f51c0SChris Bieneman   if (ResourceCount > 0)
1034a0ccfa8SKazu Hirata     support::endian::write(OS, BindingSize, llvm::endianness::little);
1042975ccb4SChris Bieneman 
105dd3f7b02SChris Bieneman   for (const auto &Res : Resources)
106dd3f7b02SChris Bieneman     OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
1070c3f51c0SChris Bieneman 
1080c3f51c0SChris Bieneman   // PSV Version 0 stops after the resource list.
1090c3f51c0SChris Bieneman   if (Version == 0)
1100c3f51c0SChris Bieneman     return;
1110c3f51c0SChris Bieneman 
112*c62c7463SCooper Partin   support::endian::write(OS,
113*c62c7463SCooper Partin                          static_cast<uint32_t>(DXConStrTabBuilder.getSize()),
1144a0ccfa8SKazu Hirata                          llvm::endianness::little);
1150c3f51c0SChris Bieneman 
1160c3f51c0SChris Bieneman   // Write the string table.
117*c62c7463SCooper Partin   DXConStrTabBuilder.write(OS);
1180c3f51c0SChris Bieneman 
1190c3f51c0SChris Bieneman   // Write the index table size, then table.
1200c3f51c0SChris Bieneman   support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()),
1214a0ccfa8SKazu Hirata                          llvm::endianness::little);
1220c3f51c0SChris Bieneman   for (auto I : IndexBuffer)
1234a0ccfa8SKazu Hirata     support::endian::write(OS, I, llvm::endianness::little);
1240c3f51c0SChris Bieneman 
1250c3f51c0SChris Bieneman   if (SignatureElements.size() > 0) {
1260c3f51c0SChris Bieneman     // write the size of the signature elements.
1270c3f51c0SChris Bieneman     support::endian::write(OS,
1280c3f51c0SChris Bieneman                            static_cast<uint32_t>(sizeof(v0::SignatureElement)),
1294a0ccfa8SKazu Hirata                            llvm::endianness::little);
1300c3f51c0SChris Bieneman 
1310c3f51c0SChris Bieneman     // write the signature elements.
1320c3f51c0SChris Bieneman     OS.write(reinterpret_cast<const char *>(&SignatureElements[0]),
1330c3f51c0SChris Bieneman              SignatureElements.size() * sizeof(v0::SignatureElement));
1340c3f51c0SChris Bieneman   }
135b799e9daSChris B 
136b799e9daSChris B   for (const auto &MaskVector : OutputVectorMasks)
137b799e9daSChris B     support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
1384a0ccfa8SKazu Hirata                                  llvm::endianness::little);
139b799e9daSChris B   support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOrPrimMasks),
1404a0ccfa8SKazu Hirata                                llvm::endianness::little);
141b799e9daSChris B   for (const auto &MaskVector : InputOutputMap)
142b799e9daSChris B     support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
1434a0ccfa8SKazu Hirata                                  llvm::endianness::little);
144b799e9daSChris B   support::endian::write_array(OS, ArrayRef<uint32_t>(InputPatchMap),
1454a0ccfa8SKazu Hirata                                llvm::endianness::little);
146b799e9daSChris B   support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),
1474a0ccfa8SKazu Hirata                                llvm::endianness::little);
148ad93908eSChris Bieneman }
1499f87522bSChris B 
finalize(Triple::EnvironmentType Stage)150*c62c7463SCooper Partin void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
151*c62c7463SCooper Partin   IsFinalized = true;
152*c62c7463SCooper Partin   BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
153*c62c7463SCooper Partin   BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
154*c62c7463SCooper Partin   BaseData.SigPatchOrPrimElements =
155*c62c7463SCooper Partin       static_cast<uint32_t>(PatchOrPrimElements.size());
156*c62c7463SCooper Partin 
157*c62c7463SCooper Partin   SmallVector<StringRef, 32> SemanticNames;
158*c62c7463SCooper Partin 
159*c62c7463SCooper Partin   // Build a string table and set associated offsets to be written when
160*c62c7463SCooper Partin   // write() is called
161*c62c7463SCooper Partin   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
162*c62c7463SCooper Partin                      SemanticNames, InputElements);
163*c62c7463SCooper Partin   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
164*c62c7463SCooper Partin                      SemanticNames, OutputElements);
165*c62c7463SCooper Partin   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
166*c62c7463SCooper Partin                      SemanticNames, PatchOrPrimElements);
167*c62c7463SCooper Partin 
168*c62c7463SCooper Partin   DXConStrTabBuilder.add(EntryName);
169*c62c7463SCooper Partin 
170*c62c7463SCooper Partin   DXConStrTabBuilder.finalize();
171*c62c7463SCooper Partin   for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
172*c62c7463SCooper Partin     llvm::dxbc::PSV::v0::SignatureElement &El = std::get<0>(ElAndName);
173*c62c7463SCooper Partin     StringRef Name = std::get<1>(ElAndName);
174*c62c7463SCooper Partin     El.NameOffset = static_cast<uint32_t>(DXConStrTabBuilder.getOffset(Name));
175*c62c7463SCooper Partin     if (sys::IsBigEndianHost)
176*c62c7463SCooper Partin       El.swapBytes();
177*c62c7463SCooper Partin   }
178*c62c7463SCooper Partin 
179*c62c7463SCooper Partin   BaseData.EntryNameOffset =
180*c62c7463SCooper Partin       static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
181*c62c7463SCooper Partin 
182*c62c7463SCooper Partin   if (!sys::IsBigEndianHost)
183*c62c7463SCooper Partin     return;
184*c62c7463SCooper Partin   BaseData.swapBytes();
185*c62c7463SCooper Partin   BaseData.swapBytes(Stage);
186*c62c7463SCooper Partin   for (auto &Res : Resources)
187*c62c7463SCooper Partin     Res.swapBytes();
188*c62c7463SCooper Partin }
189*c62c7463SCooper Partin 
write(raw_ostream & OS)1909f87522bSChris B void Signature::write(raw_ostream &OS) {
1919f87522bSChris B   SmallVector<dxbc::ProgramSignatureElement> SigParams;
1929f87522bSChris B   SigParams.reserve(Params.size());
1939f87522bSChris B   StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));
1949f87522bSChris B 
1959f87522bSChris B   // Name offsets are from the start of the part. Pre-calculate the offset to
1969f87522bSChris B   // the start of the string table so that it can be added to the table offset.
1979f87522bSChris B   uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +
1989f87522bSChris B                         (sizeof(dxbc::ProgramSignatureElement) * Params.size());
1999f87522bSChris B 
2009f87522bSChris B   for (const auto &P : Params) {
2019f87522bSChris B     // zero out the data
2029f87522bSChris B     dxbc::ProgramSignatureElement FinalElement;
2039f87522bSChris B     memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));
2049f87522bSChris B     FinalElement.Stream = P.Stream;
2059f87522bSChris B     FinalElement.NameOffset =
2069f87522bSChris B         static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;
2079f87522bSChris B     FinalElement.Index = P.Index;
2089f87522bSChris B     FinalElement.SystemValue = P.SystemValue;
2099f87522bSChris B     FinalElement.CompType = P.CompType;
2109f87522bSChris B     FinalElement.Register = P.Register;
2119f87522bSChris B     FinalElement.Mask = P.Mask;
2129f87522bSChris B     FinalElement.ExclusiveMask = P.ExclusiveMask;
2139f87522bSChris B     FinalElement.MinPrecision = P.MinPrecision;
2149f87522bSChris B     SigParams.push_back(FinalElement);
2159f87522bSChris B   }
2169f87522bSChris B 
2179f87522bSChris B   StrTabBuilder.finalizeInOrder();
2189f87522bSChris B   stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,
2199f87522bSChris B                              const dxbc::ProgramSignatureElement R) {
2209f87522bSChris B     return std::tie(L.Stream, L.Register, L.NameOffset) <
2219f87522bSChris B            std::tie(R.Stream, R.Register, R.NameOffset);
2229f87522bSChris B   });
2239f87522bSChris B   if (sys::IsBigEndianHost)
2249f87522bSChris B     for (auto &El : SigParams)
2259f87522bSChris B       El.swapBytes();
2269f87522bSChris B 
2279f87522bSChris B   dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),
2289f87522bSChris B                                          sizeof(dxbc::ProgramSignatureHeader)};
2299f87522bSChris B   if (sys::IsBigEndianHost)
2309f87522bSChris B     Header.swapBytes();
2319f87522bSChris B   OS.write(reinterpret_cast<const char *>(&Header),
2329f87522bSChris B            sizeof(dxbc::ProgramSignatureHeader));
2339f87522bSChris B   OS.write(reinterpret_cast<const char *>(SigParams.data()),
2349f87522bSChris B            sizeof(dxbc::ProgramSignatureElement) * SigParams.size());
2359f87522bSChris B   StrTabBuilder.write(OS);
2369f87522bSChris B }
237