brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.6 KiB · 7b7b8d8 Raw
702 lines · cpp
1//===- DXContainer.cpp - DXContainer object file implementation -----------===//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/Object/DXContainer.h"10#include "llvm/BinaryFormat/DXContainer.h"11#include "llvm/Object/Error.h"12#include "llvm/Support/Endian.h"13#include "llvm/Support/FormatVariadic.h"14#include "llvm/TargetParser/SubtargetFeature.h"15 16using namespace llvm;17using namespace llvm::object;18 19static Error parseFailed(const Twine &Msg) {20  return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);21}22 23template <typename T>24static Error readStruct(StringRef Buffer, const char *Src, T &Struct) {25  // Don't read before the beginning or past the end of the file26  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())27    return parseFailed("Reading structure out of file bounds");28 29  memcpy(&Struct, Src, sizeof(T));30  // DXContainer is always little endian31  if (sys::IsBigEndianHost)32    Struct.swapBytes();33  return Error::success();34}35 36template <typename T>37static Error readInteger(StringRef Buffer, const char *Src, T &Val,38                         Twine Str = "structure") {39  static_assert(std::is_integral_v<T>,40                "Cannot call readInteger on non-integral type.");41  // Don't read before the beginning or past the end of the file42  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())43    return parseFailed(Twine("Reading ") + Str + " out of file bounds");44 45  // The DXContainer offset table is comprised of uint32_t values but not padded46  // to a 64-bit boundary. So Parts may start unaligned if there is an odd47  // number of parts and part data itself is not required to be padded.48  if (reinterpret_cast<uintptr_t>(Src) % alignof(T) != 0)49    memcpy(reinterpret_cast<char *>(&Val), Src, sizeof(T));50  else51    Val = *reinterpret_cast<const T *>(Src);52  // DXContainer is always little endian53  if (sys::IsBigEndianHost)54    sys::swapByteOrder(Val);55  return Error::success();56}57 58DXContainer::DXContainer(MemoryBufferRef O) : Data(O) {}59 60Error DXContainer::parseHeader() {61  return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header);62}63 64Error DXContainer::parseDXILHeader(StringRef Part) {65  if (DXIL)66    return parseFailed("More than one DXIL part is present in the file");67  const char *Current = Part.begin();68  dxbc::ProgramHeader Header;69  if (Error Err = readStruct(Part, Current, Header))70    return Err;71  Current += offsetof(dxbc::ProgramHeader, Bitcode) + Header.Bitcode.Offset;72  DXIL.emplace(std::make_pair(Header, Current));73  return Error::success();74}75 76Error DXContainer::parseShaderFeatureFlags(StringRef Part) {77  if (ShaderFeatureFlags)78    return parseFailed("More than one SFI0 part is present in the file");79  uint64_t FlagValue = 0;80  if (Error Err = readInteger(Part, Part.begin(), FlagValue))81    return Err;82  ShaderFeatureFlags = FlagValue;83  return Error::success();84}85 86Error DXContainer::parseHash(StringRef Part) {87  if (Hash)88    return parseFailed("More than one HASH part is present in the file");89  dxbc::ShaderHash ReadHash;90  if (Error Err = readStruct(Part, Part.begin(), ReadHash))91    return Err;92  Hash = ReadHash;93  return Error::success();94}95 96Error DXContainer::parseRootSignature(StringRef Part) {97  if (RootSignature)98    return parseFailed("More than one RTS0 part is present in the file");99  RootSignature = DirectX::RootSignature(Part);100  if (Error Err = RootSignature->parse())101    return Err;102  return Error::success();103}104 105Error DXContainer::parsePSVInfo(StringRef Part) {106  if (PSVInfo)107    return parseFailed("More than one PSV0 part is present in the file");108  PSVInfo = DirectX::PSVRuntimeInfo(Part);109  // Parsing the PSVRuntime info occurs late because we need to read data from110  // other parts first.111  return Error::success();112}113 114Error DirectX::Signature::initialize(StringRef Part) {115  dxbc::ProgramSignatureHeader SigHeader;116  if (Error Err = readStruct(Part, Part.begin(), SigHeader))117    return Err;118  size_t Size = sizeof(dxbc::ProgramSignatureElement) * SigHeader.ParamCount;119 120  if (Part.size() < Size + SigHeader.FirstParamOffset)121    return parseFailed("Signature parameters extend beyond the part boundary");122 123  Parameters.Data = Part.substr(SigHeader.FirstParamOffset, Size);124 125  StringTableOffset = SigHeader.FirstParamOffset + static_cast<uint32_t>(Size);126  StringTable = Part.substr(SigHeader.FirstParamOffset + Size);127 128  for (const auto &Param : Parameters) {129    if (Param.NameOffset < StringTableOffset)130      return parseFailed("Invalid parameter name offset: name starts before "131                         "the first name offset");132    if (Param.NameOffset - StringTableOffset > StringTable.size())133      return parseFailed("Invalid parameter name offset: name starts after the "134                         "end of the part data");135  }136  return Error::success();137}138 139Error DXContainer::parsePartOffsets() {140  uint32_t LastOffset =141      sizeof(dxbc::Header) + (Header.PartCount * sizeof(uint32_t));142  const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header);143  for (uint32_t Part = 0; Part < Header.PartCount; ++Part) {144    uint32_t PartOffset;145    if (Error Err = readInteger(Data.getBuffer(), Current, PartOffset))146      return Err;147    if (PartOffset < LastOffset)148      return parseFailed(149          formatv(150              "Part offset for part {0} begins before the previous part ends",151              Part)152              .str());153    Current += sizeof(uint32_t);154    if (PartOffset >= Data.getBufferSize())155      return parseFailed("Part offset points beyond boundary of the file");156    // To prevent overflow when reading the part name, we subtract the part name157    // size from the buffer size, rather than adding to the offset. Since the158    // file header is larger than the part header we can't reach this code159    // unless the buffer is at least as large as a part header, so this160    // subtraction can't underflow.161    if (PartOffset >= Data.getBufferSize() - sizeof(dxbc::PartHeader::Name))162      return parseFailed("File not large enough to read part name");163    PartOffsets.push_back(PartOffset);164 165    dxbc::PartType PT =166        dxbc::parsePartType(Data.getBuffer().substr(PartOffset, 4));167    uint32_t PartDataStart = PartOffset + sizeof(dxbc::PartHeader);168    uint32_t PartSize;169    if (Error Err = readInteger(Data.getBuffer(),170                                Data.getBufferStart() + PartOffset + 4,171                                PartSize, "part size"))172      return Err;173    StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize);174    LastOffset = PartOffset + PartSize;175    switch (PT) {176    case dxbc::PartType::DXIL:177      if (Error Err = parseDXILHeader(PartData))178        return Err;179      break;180    case dxbc::PartType::SFI0:181      if (Error Err = parseShaderFeatureFlags(PartData))182        return Err;183      break;184    case dxbc::PartType::HASH:185      if (Error Err = parseHash(PartData))186        return Err;187      break;188    case dxbc::PartType::PSV0:189      if (Error Err = parsePSVInfo(PartData))190        return Err;191      break;192    case dxbc::PartType::ISG1:193      if (Error Err = InputSignature.initialize(PartData))194        return Err;195      break;196    case dxbc::PartType::OSG1:197      if (Error Err = OutputSignature.initialize(PartData))198        return Err;199      break;200    case dxbc::PartType::PSG1:201      if (Error Err = PatchConstantSignature.initialize(PartData))202        return Err;203      break;204    case dxbc::PartType::Unknown:205      break;206    case dxbc::PartType::RTS0:207      if (Error Err = parseRootSignature(PartData))208        return Err;209      break;210    }211  }212 213  // Fully parsing the PSVInfo requires knowing the shader kind which we read214  // out of the program header in the DXIL part.215  if (PSVInfo) {216    if (!DXIL)217      return parseFailed("Cannot fully parse pipeline state validation "218                         "information without DXIL part.");219    if (Error Err = PSVInfo->parse(DXIL->first.ShaderKind))220      return Err;221  }222  return Error::success();223}224 225Expected<DXContainer> DXContainer::create(MemoryBufferRef Object) {226  DXContainer Container(Object);227  if (Error Err = Container.parseHeader())228    return std::move(Err);229  if (Error Err = Container.parsePartOffsets())230    return std::move(Err);231  return Container;232}233 234void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) {235  StringRef Buffer = Container.Data.getBuffer();236  const char *Current = Buffer.data() + Offset;237  // Offsets are validated during parsing, so all offsets in the container are238  // valid and contain enough readable data to read a header.239  cantFail(readStruct(Buffer, Current, IteratorState.Part));240  IteratorState.Data =241      StringRef(Current + sizeof(dxbc::PartHeader), IteratorState.Part.Size);242  IteratorState.Offset = Offset;243}244 245Error DirectX::RootSignature::parse() {246  const char *Current = PartData.begin();247 248  // Root Signature headers expects 6 integers to be present.249  if (PartData.size() < 6 * sizeof(uint32_t))250    return parseFailed(251        "Invalid root signature, insufficient space for header.");252 253  Version = support::endian::read<uint32_t, llvm::endianness::little>(Current);254  Current += sizeof(uint32_t);255 256  NumParameters =257      support::endian::read<uint32_t, llvm::endianness::little>(Current);258  Current += sizeof(uint32_t);259 260  RootParametersOffset =261      support::endian::read<uint32_t, llvm::endianness::little>(Current);262  Current += sizeof(uint32_t);263 264  NumStaticSamplers =265      support::endian::read<uint32_t, llvm::endianness::little>(Current);266  Current += sizeof(uint32_t);267 268  StaticSamplersOffset =269      support::endian::read<uint32_t, llvm::endianness::little>(Current);270  Current += sizeof(uint32_t);271 272  Flags = support::endian::read<uint32_t, llvm::endianness::little>(Current);273  Current += sizeof(uint32_t);274 275  ParametersHeaders.Data = PartData.substr(276      RootParametersOffset,277      NumParameters * sizeof(dxbc::RTS0::v1::RootParameterHeader));278 279  StaticSamplers.Stride = (Version <= 2)280                              ? sizeof(dxbc::RTS0::v1::StaticSampler)281                              : sizeof(dxbc::RTS0::v3::StaticSampler);282 283  StaticSamplers.Data = PartData.substr(StaticSamplersOffset,284                                        static_cast<size_t>(NumStaticSamplers) *285                                            StaticSamplers.Stride);286 287  return Error::success();288}289 290Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {291  Triple::EnvironmentType ShaderStage = dxbc::getShaderStage(ShaderKind);292 293  const char *Current = Data.begin();294  if (Error Err = readInteger(Data, Current, Size))295    return Err;296  Current += sizeof(uint32_t);297 298  StringRef PSVInfoData = Data.substr(sizeof(uint32_t), Size);299 300  if (PSVInfoData.size() < Size)301    return parseFailed(302        "Pipeline state data extends beyond the bounds of the part");303 304  using namespace dxbc::PSV;305 306  const uint32_t PSVVersion = getVersion();307 308  // Detect the PSVVersion by looking at the size field.309  if (PSVVersion == 3) {310    v3::RuntimeInfo Info;311    if (Error Err = readStruct(PSVInfoData, Current, Info))312      return Err;313    if (sys::IsBigEndianHost)314      Info.swapBytes(ShaderStage);315    BasicInfo = Info;316  } else if (PSVVersion == 2) {317    v2::RuntimeInfo Info;318    if (Error Err = readStruct(PSVInfoData, Current, Info))319      return Err;320    if (sys::IsBigEndianHost)321      Info.swapBytes(ShaderStage);322    BasicInfo = Info;323  } else if (PSVVersion == 1) {324    v1::RuntimeInfo Info;325    if (Error Err = readStruct(PSVInfoData, Current, Info))326      return Err;327    if (sys::IsBigEndianHost)328      Info.swapBytes(ShaderStage);329    BasicInfo = Info;330  } else if (PSVVersion == 0) {331    v0::RuntimeInfo Info;332    if (Error Err = readStruct(PSVInfoData, Current, Info))333      return Err;334    if (sys::IsBigEndianHost)335      Info.swapBytes(ShaderStage);336    BasicInfo = Info;337  } else338    return parseFailed(339        "Cannot read PSV Runtime Info, unsupported PSV version.");340 341  Current += Size;342 343  uint32_t ResourceCount = 0;344  if (Error Err = readInteger(Data, Current, ResourceCount))345    return Err;346  Current += sizeof(uint32_t);347 348  if (ResourceCount > 0) {349    if (Error Err = readInteger(Data, Current, Resources.Stride))350      return Err;351    Current += sizeof(uint32_t);352 353    size_t BindingDataSize = Resources.Stride * ResourceCount;354    Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);355 356    if (Resources.Data.size() < BindingDataSize)357      return parseFailed(358          "Resource binding data extends beyond the bounds of the part");359 360    Current += BindingDataSize;361  } else362    Resources.Stride = sizeof(v2::ResourceBindInfo);363 364  // PSV version 0 ends after the resource bindings.365  if (PSVVersion == 0)366    return Error::success();367 368  // String table starts at a 4-byte offset.369  Current = reinterpret_cast<const char *>(370      alignTo<4>(reinterpret_cast<uintptr_t>(Current)));371 372  uint32_t StringTableSize = 0;373  if (Error Err = readInteger(Data, Current, StringTableSize))374    return Err;375  if (StringTableSize % 4 != 0)376    return parseFailed("String table misaligned");377  Current += sizeof(uint32_t);378  StringTable = StringRef(Current, StringTableSize);379 380  Current += StringTableSize;381 382  uint32_t SemanticIndexTableSize = 0;383  if (Error Err = readInteger(Data, Current, SemanticIndexTableSize))384    return Err;385  Current += sizeof(uint32_t);386 387  SemanticIndexTable.reserve(SemanticIndexTableSize);388  for (uint32_t I = 0; I < SemanticIndexTableSize; ++I) {389    uint32_t Index = 0;390    if (Error Err = readInteger(Data, Current, Index))391      return Err;392    Current += sizeof(uint32_t);393    SemanticIndexTable.push_back(Index);394  }395 396  uint8_t InputCount = getSigInputCount();397  uint8_t OutputCount = getSigOutputCount();398  uint8_t PatchOrPrimCount = getSigPatchOrPrimCount();399 400  uint32_t ElementCount = InputCount + OutputCount + PatchOrPrimCount;401 402  if (ElementCount > 0) {403    if (Error Err = readInteger(Data, Current, SigInputElements.Stride))404      return Err;405    Current += sizeof(uint32_t);406    // Assign the stride to all the arrays.407    SigOutputElements.Stride = SigPatchOrPrimElements.Stride =408        SigInputElements.Stride;409 410    if (Data.end() - Current <411        (ptrdiff_t)(ElementCount * SigInputElements.Stride))412      return parseFailed(413          "Signature elements extend beyond the size of the part");414 415    size_t InputSize = SigInputElements.Stride * InputCount;416    SigInputElements.Data = Data.substr(Current - Data.begin(), InputSize);417    Current += InputSize;418 419    size_t OutputSize = SigOutputElements.Stride * OutputCount;420    SigOutputElements.Data = Data.substr(Current - Data.begin(), OutputSize);421    Current += OutputSize;422 423    size_t PSize = SigPatchOrPrimElements.Stride * PatchOrPrimCount;424    SigPatchOrPrimElements.Data = Data.substr(Current - Data.begin(), PSize);425    Current += PSize;426  }427 428  ArrayRef<uint8_t> OutputVectorCounts = getOutputVectorCounts();429  uint8_t PatchConstOrPrimVectorCount = getPatchConstOrPrimVectorCount();430  uint8_t InputVectorCount = getInputVectorCount();431 432  auto maskDwordSize = [](uint8_t Vector) {433    return (static_cast<uint32_t>(Vector) + 7) >> 3;434  };435 436  auto mapTableSize = [maskDwordSize](uint8_t X, uint8_t Y) {437    return maskDwordSize(Y) * X * 4;438  };439 440  if (usesViewID()) {441    for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {442      // The vector mask is one bit per component and 4 components per vector.443      // We can compute the number of dwords required by rounding up to the next444      // multiple of 8.445      uint32_t NumDwords =446          maskDwordSize(static_cast<uint32_t>(OutputVectorCounts[I]));447      size_t NumBytes = NumDwords * sizeof(uint32_t);448      OutputVectorMasks[I].Data = Data.substr(Current - Data.begin(), NumBytes);449      Current += NumBytes;450    }451 452    if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0) {453      uint32_t NumDwords = maskDwordSize(PatchConstOrPrimVectorCount);454      size_t NumBytes = NumDwords * sizeof(uint32_t);455      PatchOrPrimMasks.Data = Data.substr(Current - Data.begin(), NumBytes);456      Current += NumBytes;457    }458  }459 460  // Input/Output mapping table461  for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {462    if (InputVectorCount == 0 || OutputVectorCounts[I] == 0)463      continue;464    uint32_t NumDwords = mapTableSize(InputVectorCount, OutputVectorCounts[I]);465    size_t NumBytes = NumDwords * sizeof(uint32_t);466    InputOutputMap[I].Data = Data.substr(Current - Data.begin(), NumBytes);467    Current += NumBytes;468  }469 470  // Hull shader: Input/Patch mapping table471  if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0 &&472      InputVectorCount > 0) {473    uint32_t NumDwords =474        mapTableSize(InputVectorCount, PatchConstOrPrimVectorCount);475    size_t NumBytes = NumDwords * sizeof(uint32_t);476    InputPatchMap.Data = Data.substr(Current - Data.begin(), NumBytes);477    Current += NumBytes;478  }479 480  // Domain Shader: Patch/Output mapping table481  if (ShaderStage == Triple::Domain && PatchConstOrPrimVectorCount > 0 &&482      OutputVectorCounts[0] > 0) {483    uint32_t NumDwords =484        mapTableSize(PatchConstOrPrimVectorCount, OutputVectorCounts[0]);485    size_t NumBytes = NumDwords * sizeof(uint32_t);486    PatchOutputMap.Data = Data.substr(Current - Data.begin(), NumBytes);487    Current += NumBytes;488  }489 490  return Error::success();491}492 493uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const {494  if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))495    return P->SigInputElements;496  if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))497    return P->SigInputElements;498  if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))499    return P->SigInputElements;500  return 0;501}502 503uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const {504  if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))505    return P->SigOutputElements;506  if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))507    return P->SigOutputElements;508  if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))509    return P->SigOutputElements;510  return 0;511}512 513uint8_t DirectX::PSVRuntimeInfo::getSigPatchOrPrimCount() const {514  if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))515    return P->SigPatchOrPrimElements;516  if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))517    return P->SigPatchOrPrimElements;518  if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))519    return P->SigPatchOrPrimElements;520  return 0;521}522 523class DXNotSupportedError : public ErrorInfo<DXNotSupportedError> {524public:525  static char ID;526 527  DXNotSupportedError(StringRef S) : FeatureString(S) {}528 529  void log(raw_ostream &OS) const override {530    OS << "DXContainer does not support " << FeatureString;531  }532 533  std::error_code convertToErrorCode() const override {534    return inconvertibleErrorCode();535  }536 537private:538  StringRef FeatureString;539};540 541char DXNotSupportedError::ID = 0;542 543Expected<section_iterator>544DXContainerObjectFile::getSymbolSection(DataRefImpl Symb) const {545  return make_error<DXNotSupportedError>("Symbol sections");546}547 548Expected<StringRef> DXContainerObjectFile::getSymbolName(DataRefImpl) const {549  return make_error<DXNotSupportedError>("Symbol names");550}551 552Expected<uint64_t>553DXContainerObjectFile::getSymbolAddress(DataRefImpl Symb) const {554  return make_error<DXNotSupportedError>("Symbol addresses");555}556 557uint64_t DXContainerObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {558  llvm_unreachable("DXContainer does not support symbols");559}560uint64_t561DXContainerObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {562  llvm_unreachable("DXContainer does not support symbols");563}564 565Expected<SymbolRef::Type>566DXContainerObjectFile::getSymbolType(DataRefImpl Symb) const {567  return make_error<DXNotSupportedError>("Symbol types");568}569 570void DXContainerObjectFile::moveSectionNext(DataRefImpl &Sec) const {571  PartIterator It = reinterpret_cast<PartIterator>(Sec.p);572  if (It == Parts.end())573    return;574 575  ++It;576  Sec.p = reinterpret_cast<uintptr_t>(It);577}578 579Expected<StringRef>580DXContainerObjectFile::getSectionName(DataRefImpl Sec) const {581  PartIterator It = reinterpret_cast<PartIterator>(Sec.p);582  return StringRef(It->Part.getName());583}584 585uint64_t DXContainerObjectFile::getSectionAddress(DataRefImpl Sec) const {586  PartIterator It = reinterpret_cast<PartIterator>(Sec.p);587  return It->Offset;588}589 590uint64_t DXContainerObjectFile::getSectionIndex(DataRefImpl Sec) const {591  return (Sec.p - reinterpret_cast<uintptr_t>(Parts.begin())) /592         sizeof(PartIterator);593}594 595uint64_t DXContainerObjectFile::getSectionSize(DataRefImpl Sec) const {596  PartIterator It = reinterpret_cast<PartIterator>(Sec.p);597  return It->Data.size();598}599Expected<ArrayRef<uint8_t>>600DXContainerObjectFile::getSectionContents(DataRefImpl Sec) const {601  PartIterator It = reinterpret_cast<PartIterator>(Sec.p);602  return ArrayRef<uint8_t>(It->Data.bytes_begin(), It->Data.size());603}604 605uint64_t DXContainerObjectFile::getSectionAlignment(DataRefImpl Sec) const {606  return 1;607}608 609bool DXContainerObjectFile::isSectionCompressed(DataRefImpl Sec) const {610  return false;611}612 613bool DXContainerObjectFile::isSectionText(DataRefImpl Sec) const {614  return false;615}616 617bool DXContainerObjectFile::isSectionData(DataRefImpl Sec) const {618  return false;619}620 621bool DXContainerObjectFile::isSectionBSS(DataRefImpl Sec) const {622  return false;623}624 625bool DXContainerObjectFile::isSectionVirtual(DataRefImpl Sec) const {626  return false;627}628 629relocation_iterator630DXContainerObjectFile::section_rel_begin(DataRefImpl Sec) const {631  return relocation_iterator(RelocationRef());632}633 634relocation_iterator635DXContainerObjectFile::section_rel_end(DataRefImpl Sec) const {636  return relocation_iterator(RelocationRef());637}638 639void DXContainerObjectFile::moveRelocationNext(DataRefImpl &Rel) const {640  llvm_unreachable("DXContainer does not support relocations");641}642 643uint64_t DXContainerObjectFile::getRelocationOffset(DataRefImpl Rel) const {644  llvm_unreachable("DXContainer does not support relocations");645}646 647symbol_iterator648DXContainerObjectFile::getRelocationSymbol(DataRefImpl Rel) const {649  return symbol_iterator(SymbolRef());650}651 652uint64_t DXContainerObjectFile::getRelocationType(DataRefImpl Rel) const {653  llvm_unreachable("DXContainer does not support relocations");654}655 656void DXContainerObjectFile::getRelocationTypeName(657    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {658  llvm_unreachable("DXContainer does not support relocations");659}660 661section_iterator DXContainerObjectFile::section_begin() const {662  DataRefImpl Sec;663  Sec.p = reinterpret_cast<uintptr_t>(Parts.begin());664  return section_iterator(SectionRef(Sec, this));665}666section_iterator DXContainerObjectFile::section_end() const {667  DataRefImpl Sec;668  Sec.p = reinterpret_cast<uintptr_t>(Parts.end());669  return section_iterator(SectionRef(Sec, this));670}671 672uint8_t DXContainerObjectFile::getBytesInAddress() const { return 4; }673 674StringRef DXContainerObjectFile::getFileFormatName() const {675  return "DirectX Container";676}677 678Triple::ArchType DXContainerObjectFile::getArch() const { return Triple::dxil; }679 680Expected<SubtargetFeatures> DXContainerObjectFile::getFeatures() const {681  return SubtargetFeatures();682}683 684Error DXContainerObjectFile::printSymbolName(raw_ostream &OS,685                                             DataRefImpl Symb) const {686  return make_error<DXNotSupportedError>("Symbol names");687}688 689Expected<uint32_t>690DXContainerObjectFile::getSymbolFlags(DataRefImpl Symb) const {691  return make_error<DXNotSupportedError>("Symbol flags");692}693 694Expected<std::unique_ptr<DXContainerObjectFile>>695ObjectFile::createDXContainerObjectFile(MemoryBufferRef Object) {696  auto ExC = DXContainer::create(Object);697  if (!ExC)698    return ExC.takeError();699  std::unique_ptr<DXContainerObjectFile> Obj(new DXContainerObjectFile(*ExC));700  return std::move(Obj);701}702