2020#include " llvm/ADT/Twine.h"
2121#include " llvm/BinaryFormat/DXContainer.h"
2222#include " llvm/Object/Error.h"
23+ #include " llvm/Support/Endian.h"
2324#include " llvm/Support/Error.h"
2425#include " llvm/Support/MemoryBufferRef.h"
2526#include " llvm/TargetParser/Triple.h"
@@ -177,6 +178,50 @@ struct RootDescriptorView : RootParameterView {
177178 }
178179};
179180
181+ struct DescriptorTable {
182+ uint32_t NumRanges;
183+ uint32_t RangesOffset;
184+ ViewArray<dxbc::RTS0::v2::DescriptorRange> Ranges;
185+
186+ typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator begin () const {
187+ return Ranges.begin ();
188+ }
189+
190+ typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end () const {
191+ return Ranges.end ();
192+ }
193+ };
194+
195+ struct DescriptorTableView : RootParameterView {
196+ static bool classof (const RootParameterView *V) {
197+ return (V->Header .ParameterType ==
198+ llvm::to_underlying (dxbc::RootParameterType::DescriptorTable));
199+ }
200+
201+ // Define a type alias to access the template parameter from inside classof
202+ llvm::Expected<DescriptorTable> read (uint32_t Version) {
203+ const char *Current = ParamData.begin ();
204+ DescriptorTable Table;
205+
206+ Table.NumRanges =
207+ support::endian::read<uint32_t , llvm::endianness::little>(Current);
208+ Current += sizeof (uint32_t );
209+
210+ Table.RangesOffset =
211+ support::endian::read<uint32_t , llvm::endianness::little>(Current);
212+ Current += sizeof (uint32_t );
213+
214+ size_t RangeSize = sizeof (dxbc::RTS0::v1::DescriptorRange);
215+ if (Version > 1 )
216+ RangeSize = sizeof (dxbc::RTS0::v2::DescriptorRange);
217+
218+ Table.Ranges .Stride = RangeSize;
219+ Table.Ranges .Data =
220+ ParamData.substr (2 * sizeof (uint32_t ), Table.NumRanges * RangeSize);
221+ return Table;
222+ }
223+ };
224+
180225static Error parseFailed (const Twine &Msg) {
181226 return make_error<GenericBinaryError>(Msg.str (), object_error::parse_failed);
182227}
@@ -213,6 +258,9 @@ class RootSignature {
213258 llvm::Expected<RootParameterView>
214259 getParameter (const dxbc::RTS0::v1::RootParameterHeader &Header) const {
215260 size_t DataSize;
261+ size_t EndOfSectionByte = getNumStaticSamplers () == 0
262+ ? PartData.size ()
263+ : getStaticSamplersOffset ();
216264
217265 if (!dxbc::isValidParameterType (Header.ParameterType ))
218266 return parseFailed (" invalid parameter type" );
@@ -229,11 +277,23 @@ class RootSignature {
229277 else
230278 DataSize = sizeof (dxbc::RTS0::v2::RootDescriptor);
231279 break ;
232- }
233- size_t EndOfSectionByte = getNumStaticSamplers () == 0
234- ? PartData.size ()
235- : getStaticSamplersOffset ();
280+ case dxbc::RootParameterType::DescriptorTable:
281+ if (Header.ParameterOffset + sizeof (uint32_t ) > EndOfSectionByte)
282+ return parseFailed (" Reading structure out of file bounds" );
236283
284+ uint32_t NumRanges =
285+ support::endian::read<uint32_t , llvm::endianness::little>(
286+ PartData.begin () + Header.ParameterOffset );
287+ if (Version == 1 )
288+ DataSize = sizeof (dxbc::RTS0::v1::DescriptorRange) * NumRanges;
289+ else
290+ DataSize = sizeof (dxbc::RTS0::v2::DescriptorRange) * NumRanges;
291+
292+ // 4 bytes for the number of ranges in table and
293+ // 4 bytes for the ranges offset
294+ DataSize += 2 * sizeof (uint32_t );
295+ break ;
296+ }
237297 if (Header.ParameterOffset + DataSize > EndOfSectionByte)
238298 return parseFailed (" Reading structure out of file bounds" );
239299
0 commit comments