LLVM  15.0.0git
DXContainer.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "llvm/Object/Error.h"
12 
13 using namespace llvm;
14 using namespace llvm::object;
15 
16 static Error parseFailed(const Twine &Msg) {
17  return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
18 }
19 
20 template <typename T>
21 static Error readStruct(StringRef Buffer, const char *Src, T &Struct) {
22  // Don't read before the beginning or past the end of the file
23  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
24  return parseFailed("Reading structure out of file bounds");
25 
26  memcpy(&Struct, Src, sizeof(T));
27  // DXContainer is always little endian
29  Struct.swapBytes();
30  return Error::success();
31 }
32 
33 template <typename T>
34 static Error readInteger(StringRef Buffer, const char *Src, T &Val) {
35  static_assert(std::is_integral<T>::value,
36  "Cannot call readInteger on non-integral type.");
37  assert(reinterpret_cast<uintptr_t>(Src) % alignof(T) == 0 &&
38  "Unaligned read of value from buffer!");
39  // Don't read before the beginning or past the end of the file
40  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
41  return parseFailed("Reading structure out of file bounds");
42 
43  Val = *reinterpret_cast<const T *>(Src);
44  // DXContainer is always little endian
46  sys::swapByteOrder(Val);
47  return Error::success();
48 }
49 
50 DXContainer::DXContainer(MemoryBufferRef O) : Data(O) {}
51 
53  return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header);
54 }
55 
56 Error DXContainer::parseDXILHeader(uint32_t Offset) {
57  if (DXIL)
58  return parseFailed("More than one DXIL part is present in the file");
59  const char *Current = Data.getBuffer().data() + Offset;
60  dxbc::ProgramHeader Header;
61  if (Error Err = readStruct(Data.getBuffer(), Current, Header))
62  return Err;
63  Current += offsetof(dxbc::ProgramHeader, Bitcode) + Header.Bitcode.Offset;
64  DXIL.emplace(std::make_pair(Header, Current));
65  return Error::success();
66 }
67 
68 Error DXContainer::parsePartOffsets() {
69  const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header);
70  for (uint32_t Part = 0; Part < Header.PartCount; ++Part) {
71  uint32_t PartOffset;
72  if (Error Err = readInteger(Data.getBuffer(), Current, PartOffset))
73  return Err;
74  Current += sizeof(uint32_t);
75  // We need to ensure that each part offset leaves enough space for a part
76  // header. To prevent overflow, we subtract the part header size from the
77  // buffer size, rather than adding to the offset. Since the file header is
78  // larger than the part header we can't reach this code unless the buffer
79  // is larger than the part header, so this can't underflow.
80  if (PartOffset > Data.getBufferSize() - sizeof(dxbc::PartHeader))
81  return parseFailed("Part offset points beyond boundary of the file");
82  PartOffsets.push_back(PartOffset);
83 
84  // If this isn't a dxil part stop here...
85  if (Data.getBuffer().substr(PartOffset, 4) != "DXIL")
86  continue;
87  if (Error Err = parseDXILHeader(PartOffset + sizeof(dxbc::PartHeader)))
88  return Err;
89  }
90  return Error::success();
91 }
92 
94  DXContainer Container(Object);
95  if (Error Err = Container.parseHeader())
96  return std::move(Err);
97  if (Error Err = Container.parsePartOffsets())
98  return std::move(Err);
99  return Container;
100 }
101 
102 void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) {
103  StringRef Buffer = Container.Data.getBuffer();
104  const char *Current = Buffer.data() + Offset;
105  // Offsets are validated during parsing, so all offsets in the container are
106  // valid and contain enough readable data to read a header.
107  cantFail(readStruct(Buffer, Current, IteratorState.Part));
108  IteratorState.Data =
109  StringRef(Current + sizeof(dxbc::PartHeader), IteratorState.Part.Size);
110  IteratorState.Offset = Offset;
111 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::sys::IsBigEndianHost
constexpr bool IsBigEndianHost
Definition: SwapByteOrder.h:98
llvm::sys::swapByteOrder
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:158
T
offsetof
#define offsetof(TYPE, MEMBER)
Definition: AMDHSAKernelDescriptor.h:23
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
parseHeader
static void parseHeader(const MachOObjectFile &Obj, T &Header, Error &Err)
Definition: MachOObjectFile.cpp:227
llvm::MemoryBufferRef::getBufferSize
size_t getBufferSize() const
Definition: MemoryBufferRef.h:37
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::StringRef::substr
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:615
readStruct
static Error readStruct(StringRef Buffer, const char *Src, T &Struct)
Definition: DXContainer.cpp:21
llvm::object
Definition: DWARFDebugLoc.h:25
Error.h
llvm::dxbc::PartHeader
Use this type to describe the size and type of a DXIL container part.
Definition: DXContainer.h:83
llvm::object::object_error::parse_failed
@ parse_failed
Bitcode
write Write Bitcode
Definition: BitcodeWriterPass.cpp:73
llvm::object::DXContainer::create
static Expected< DXContainer > create(MemoryBufferRef Object)
Definition: DXContainer.cpp:93
llvm::OutputFileType::Object
@ Object
readInteger
static Error readInteger(StringRef Buffer, const char *Src, T &Val)
Definition: DXContainer.cpp:34
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:240
DXContainer.h
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:416
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:130
llvm::Optional::emplace
void emplace(ArgTypes &&... Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:287
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::MemoryBufferRef::getBuffer
StringRef getBuffer() const
Definition: MemoryBufferRef.h:32
DXContainer.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:745
uint32_t
llvm::AMDGPU::SendMsg::Msg
const CustomOperand< const MCSubtargetInfo & > Msg[]
Definition: AMDGPUAsmUtils.cpp:39
llvm::object::DXContainer
Definition: DXContainer.h:27
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::dxbc::BitcodeHeader::Offset
uint32_t Offset
Definition: DXContainer.h:99
llvm::dxbc::ProgramHeader::Bitcode
BitcodeHeader Bitcode
Definition: DXContainer.h:117
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
llvm::dxbc::Header
Definition: DXContainer.h:66
parseFailed
static Error parseFailed(const Twine &Msg)
Definition: DXContainer.cpp:16
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::dxbc::ProgramHeader
Definition: DXContainer.h:111