Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/MC/DXContainerPSVInfo.cpp
35233 views
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
//===----------------------------------------------------------------------===//
8
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"
14
15
using namespace llvm;
16
using namespace llvm::mcdxbc;
17
using namespace llvm::dxbc::PSV;
18
19
static constexpr size_t npos = StringRef::npos;
20
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;
30
}
31
return npos;
32
}
33
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);
44
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;
57
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);
66
}
67
}
68
69
void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
70
assert(IsFinalized && "finalize must be called before write");
71
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
InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);
85
BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
86
break;
87
case 3:
88
default:
89
InfoSize = sizeof(dxbc::PSV::v3::RuntimeInfo);
90
BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
91
}
92
93
// Write the size of the info.
94
support::endian::write(OS, InfoSize, llvm::endianness::little);
95
96
// Write the info itself.
97
OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);
98
99
uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());
100
101
support::endian::write(OS, ResourceCount, llvm::endianness::little);
102
if (ResourceCount > 0)
103
support::endian::write(OS, BindingSize, llvm::endianness::little);
104
105
for (const auto &Res : Resources)
106
OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
107
108
// PSV Version 0 stops after the resource list.
109
if (Version == 0)
110
return;
111
112
support::endian::write(OS,
113
static_cast<uint32_t>(DXConStrTabBuilder.getSize()),
114
llvm::endianness::little);
115
116
// Write the string table.
117
DXConStrTabBuilder.write(OS);
118
119
// Write the index table size, then table.
120
support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()),
121
llvm::endianness::little);
122
for (auto I : IndexBuffer)
123
support::endian::write(OS, I, llvm::endianness::little);
124
125
if (SignatureElements.size() > 0) {
126
// write the size of the signature elements.
127
support::endian::write(OS,
128
static_cast<uint32_t>(sizeof(v0::SignatureElement)),
129
llvm::endianness::little);
130
131
// write the signature elements.
132
OS.write(reinterpret_cast<const char *>(&SignatureElements[0]),
133
SignatureElements.size() * sizeof(v0::SignatureElement));
134
}
135
136
for (const auto &MaskVector : OutputVectorMasks)
137
support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
138
llvm::endianness::little);
139
support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOrPrimMasks),
140
llvm::endianness::little);
141
for (const auto &MaskVector : InputOutputMap)
142
support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),
143
llvm::endianness::little);
144
support::endian::write_array(OS, ArrayRef<uint32_t>(InputPatchMap),
145
llvm::endianness::little);
146
support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),
147
llvm::endianness::little);
148
}
149
150
void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
151
IsFinalized = true;
152
BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
153
BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
154
BaseData.SigPatchOrPrimElements =
155
static_cast<uint32_t>(PatchOrPrimElements.size());
156
157
SmallVector<StringRef, 32> SemanticNames;
158
159
// Build a string table and set associated offsets to be written when
160
// write() is called
161
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
162
SemanticNames, InputElements);
163
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
164
SemanticNames, OutputElements);
165
ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
166
SemanticNames, PatchOrPrimElements);
167
168
DXConStrTabBuilder.add(EntryName);
169
170
DXConStrTabBuilder.finalize();
171
for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
172
llvm::dxbc::PSV::v0::SignatureElement &El = std::get<0>(ElAndName);
173
StringRef Name = std::get<1>(ElAndName);
174
El.NameOffset = static_cast<uint32_t>(DXConStrTabBuilder.getOffset(Name));
175
if (sys::IsBigEndianHost)
176
El.swapBytes();
177
}
178
179
BaseData.EntryNameOffset =
180
static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
181
182
if (!sys::IsBigEndianHost)
183
return;
184
BaseData.swapBytes();
185
BaseData.swapBytes(Stage);
186
for (auto &Res : Resources)
187
Res.swapBytes();
188
}
189
190
void Signature::write(raw_ostream &OS) {
191
SmallVector<dxbc::ProgramSignatureElement> SigParams;
192
SigParams.reserve(Params.size());
193
StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));
194
195
// Name offsets are from the start of the part. Pre-calculate the offset to
196
// the start of the string table so that it can be added to the table offset.
197
uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +
198
(sizeof(dxbc::ProgramSignatureElement) * Params.size());
199
200
for (const auto &P : Params) {
201
// zero out the data
202
dxbc::ProgramSignatureElement FinalElement;
203
memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));
204
FinalElement.Stream = P.Stream;
205
FinalElement.NameOffset =
206
static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;
207
FinalElement.Index = P.Index;
208
FinalElement.SystemValue = P.SystemValue;
209
FinalElement.CompType = P.CompType;
210
FinalElement.Register = P.Register;
211
FinalElement.Mask = P.Mask;
212
FinalElement.ExclusiveMask = P.ExclusiveMask;
213
FinalElement.MinPrecision = P.MinPrecision;
214
SigParams.push_back(FinalElement);
215
}
216
217
StrTabBuilder.finalizeInOrder();
218
stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,
219
const dxbc::ProgramSignatureElement R) {
220
return std::tie(L.Stream, L.Register, L.NameOffset) <
221
std::tie(R.Stream, R.Register, R.NameOffset);
222
});
223
if (sys::IsBigEndianHost)
224
for (auto &El : SigParams)
225
El.swapBytes();
226
227
dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),
228
sizeof(dxbc::ProgramSignatureHeader)};
229
if (sys::IsBigEndianHost)
230
Header.swapBytes();
231
OS.write(reinterpret_cast<const char *>(&Header),
232
sizeof(dxbc::ProgramSignatureHeader));
233
OS.write(reinterpret_cast<const char *>(SigParams.data()),
234
sizeof(dxbc::ProgramSignatureElement) * SigParams.size());
235
StrTabBuilder.write(OS);
236
}
237
238