brintos

brintos / llvm-project-archived public Read only

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