[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / MC / DXContainerPSVInfo.cpp
blob48182fcd31df0677ed5be253a859cd2b914ecb41
1 //===- llvm/MC/DXContainerPSVInfo.cpp - DXContainer PSVInfo -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/DXContainerPSVInfo.h"
10 #include "llvm/BinaryFormat/DXContainer.h"
11 #include "llvm/MC/StringTableBuilder.h"
12 #include "llvm/Support/EndianStream.h"
13 #include "llvm/Support/raw_ostream.h"
15 using namespace llvm;
16 using namespace llvm::mcdxbc;
17 using namespace llvm::dxbc::PSV;
19 static constexpr size_t npos = StringRef::npos;
21 static size_t FindSequence(ArrayRef<uint32_t> Buffer,
22 ArrayRef<uint32_t> Sequence) {
23 if (Buffer.size() < Sequence.size())
24 return npos;
25 for (size_t Idx = 0; Idx <= Buffer.size() - Sequence.size(); ++Idx) {
26 if (0 == memcmp(static_cast<const void *>(&Buffer[Idx]),
27 static_cast<const void *>(Sequence.begin()),
28 Sequence.size() * sizeof(uint32_t)))
29 return Idx;
31 return npos;
34 static void
35 ProcessElementList(StringTableBuilder &StrTabBuilder,
36 SmallVectorImpl<uint32_t> &IndexBuffer,
37 SmallVectorImpl<v0::SignatureElement> &FinalElements,
38 SmallVectorImpl<StringRef> &SemanticNames,
39 ArrayRef<PSVSignatureElement> Elements) {
40 for (const auto &El : Elements) {
41 // Put the name in the string table and the name list.
42 StrTabBuilder.add(El.Name);
43 SemanticNames.push_back(El.Name);
45 v0::SignatureElement FinalElement;
46 memset(&FinalElement, 0, sizeof(v0::SignatureElement));
47 FinalElement.Rows = static_cast<uint8_t>(El.Indices.size());
48 FinalElement.StartRow = El.StartRow;
49 FinalElement.Cols = El.Cols;
50 FinalElement.StartCol = El.StartCol;
51 FinalElement.Allocated = El.Allocated;
52 FinalElement.Kind = El.Kind;
53 FinalElement.Type = El.Type;
54 FinalElement.Mode = El.Mode;
55 FinalElement.DynamicMask = El.DynamicMask;
56 FinalElement.Stream = El.Stream;
58 size_t Idx = FindSequence(IndexBuffer, El.Indices);
59 if (Idx == npos) {
60 FinalElement.IndicesOffset = static_cast<uint32_t>(IndexBuffer.size());
61 IndexBuffer.insert(IndexBuffer.end(), El.Indices.begin(),
62 El.Indices.end());
63 } else
64 FinalElement.IndicesOffset = static_cast<uint32_t>(Idx);
65 FinalElements.push_back(FinalElement);
69 void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
70 assert(IsFinalized && "finalize must be called before write");
72 uint32_t InfoSize;
73 uint32_t BindingSize;
74 switch (Version) {
75 case 0:
76 InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo);
77 BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
78 break;
79 case 1:
80 InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo);
81 BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
82 break;
83 case 2:
84 default:
85 InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);
86 BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
88 // Write the size of the info.
90 support::endian::write(OS, InfoSize, llvm::endianness::little);
91 // Write the info itself.
92 OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);
94 uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());
96 support::endian::write(OS, ResourceCount, llvm::endianness::little);
97 if (ResourceCount > 0)
98 support::endian::write(OS, BindingSize, llvm::endianness::little);
100 for (const auto &Res : Resources)
101 OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
103 // PSV Version 0 stops after the resource list.
104 if (Version == 0)
105 return;
107 StringTableBuilder StrTabBuilder((StringTableBuilder::DXContainer));
108 SmallVector<uint32_t, 64> IndexBuffer;
109 SmallVector<v0::SignatureElement, 32> SignatureElements;
110 SmallVector<StringRef, 32> SemanticNames;
112 ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements,
113 SemanticNames, InputElements);
114 ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements,
115 SemanticNames, OutputElements);
116 ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements,
117 SemanticNames, PatchOrPrimElements);
119 StrTabBuilder.finalize();
120 for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
121 v0::SignatureElement &El = std::get<0>(ElAndName);
122 StringRef Name = std::get<1>(ElAndName);
123 El.NameOffset = static_cast<uint32_t>(StrTabBuilder.getOffset(Name));
124 if (sys::IsBigEndianHost)
125 El.swapBytes();
128 support::endian::write(OS, static_cast<uint32_t>(StrTabBuilder.getSize()),
129 llvm::endianness::little);
131 // Write the string table.
132 StrTabBuilder.write(OS);
134 // Write the index table size, then table.
135 support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()),
136 llvm::endianness::little);
137 for (auto I : IndexBuffer)
138 support::endian::write(OS, I, llvm::endianness::little);
140 if (SignatureElements.size() > 0) {
141 // write the size of the signature elements.
142 support::endian::write(OS,
143 static_cast<uint32_t>(sizeof(v0::SignatureElement)),
144 llvm::endianness::little);
146 // write the signature elements.
147 OS.write(reinterpret_cast<const char *>(&SignatureElements[0]),
148 SignatureElements.size() * sizeof(v0::SignatureElement));
151 for (const auto &MaskVector : OutputVectorMasks)
152 support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
153 llvm::endianness::little);
154 support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOrPrimMasks),
155 llvm::endianness::little);
156 for (const auto &MaskVector : InputOutputMap)
157 support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
158 llvm::endianness::little);
159 support::endian::write_array(OS, ArrayRef<uint32_t>(InputPatchMap),
160 llvm::endianness::little);
161 support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),
162 llvm::endianness::little);
165 void Signature::write(raw_ostream &OS) {
166 SmallVector<dxbc::ProgramSignatureElement> SigParams;
167 SigParams.reserve(Params.size());
168 StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));
170 // Name offsets are from the start of the part. Pre-calculate the offset to
171 // the start of the string table so that it can be added to the table offset.
172 uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +
173 (sizeof(dxbc::ProgramSignatureElement) * Params.size());
175 for (const auto &P : Params) {
176 // zero out the data
177 dxbc::ProgramSignatureElement FinalElement;
178 memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));
179 FinalElement.Stream = P.Stream;
180 FinalElement.NameOffset =
181 static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;
182 FinalElement.Index = P.Index;
183 FinalElement.SystemValue = P.SystemValue;
184 FinalElement.CompType = P.CompType;
185 FinalElement.Register = P.Register;
186 FinalElement.Mask = P.Mask;
187 FinalElement.ExclusiveMask = P.ExclusiveMask;
188 FinalElement.MinPrecision = P.MinPrecision;
189 SigParams.push_back(FinalElement);
192 StrTabBuilder.finalizeInOrder();
193 stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,
194 const dxbc::ProgramSignatureElement R) {
195 return std::tie(L.Stream, L.Register, L.NameOffset) <
196 std::tie(R.Stream, R.Register, R.NameOffset);
198 if (sys::IsBigEndianHost)
199 for (auto &El : SigParams)
200 El.swapBytes();
202 dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),
203 sizeof(dxbc::ProgramSignatureHeader)};
204 if (sys::IsBigEndianHost)
205 Header.swapBytes();
206 OS.write(reinterpret_cast<const char *>(&Header),
207 sizeof(dxbc::ProgramSignatureHeader));
208 OS.write(reinterpret_cast<const char *>(SigParams.data()),
209 sizeof(dxbc::ProgramSignatureElement) * SigParams.size());
210 StrTabBuilder.write(OS);