[llvm] 4070aa0 - [Object][DX] Initial DXContainer parsing support
Chris Bieneman via llvm-commits
llvm-commits at lists.llvm.org
Mon May 2 11:57:11 PDT 2022
Author: Chris Bieneman
Date: 2022-05-02T13:56:33-05:00
New Revision: 4070aa01561c6bf2a5954d68228f373386658cde
URL: https://github.com/llvm/llvm-project/commit/4070aa01561c6bf2a5954d68228f373386658cde
DIFF: https://github.com/llvm/llvm-project/commit/4070aa01561c6bf2a5954d68228f373386658cde.diff
LOG: [Object][DX] Initial DXContainer parsing support
This patch begins adding DXContainer parsing support to libObject.
Following the pattern used by ELFFile my goal here is to write a
standalone DXContainer parser and later write an adapter interface to
support a subset of the ObjectFile interfaces so that we can add
limited objdump support. I will also be adding ObjectYAML support to
help drive testing of the object tools and MC-level object writers as
those come together.
DXContainer is a slightly odd format. It is arranged in "parts" that
are semantically similar to sections, but it doesn't support symbol
listing.
Reviewed By: MaskRay
Differential Revision: https://reviews.llvm.org/D124643
Added:
llvm/include/llvm/BinaryFormat/DXContainer.h
llvm/include/llvm/Object/DXContainer.h
llvm/lib/Object/DXContainer.cpp
llvm/unittests/Object/DXContainerTest.cpp
Modified:
llvm/lib/Object/CMakeLists.txt
llvm/unittests/Object/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
new file mode 100644
index 0000000000000..f9ec9fe45a0cb
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -0,0 +1,91 @@
+//===-- llvm/BinaryFormat/DXContainer.h - The DXBC file format --*- C++/-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines manifest constants for the DXContainer object file format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_DXCONTAINER_H
+#define LLVM_BINARYFORMAT_DXCONTAINER_H
+
+#include "llvm/Support/SwapByteOrder.h"
+
+#include <stdint.h>
+
+namespace llvm {
+
+// The DXContainer file format is arranged as a header and "parts". Semantically
+// parts are similar to sections in other object file formats. The File format
+// structure is roughly:
+
+// ┌────────────────────────────────┐
+// │ Header │
+// ├────────────────────────────────┤
+// │ Part │
+// ├────────────────────────────────┤
+// │ Part │
+// ├────────────────────────────────┤
+// │ ... │
+// └────────────────────────────────┘
+
+namespace dxbc {
+
+struct Hash {
+ uint8_t Digest[16];
+};
+
+enum class HashFlags : uint32_t {
+ None = 0, // No flags defined.
+ IncludesSource = 1, // This flag indicates that the shader hash was computed
+ // taking into account source information (-Zss)
+};
+
+struct ShaderHash {
+ uint32_t Flags; // DxilShaderHashFlags
+ uint8_t Digest[16];
+
+ void byteSwap() { sys::swapByteOrder(Flags); }
+};
+
+struct ContainerVersion {
+ uint16_t Major;
+ uint16_t Minor;
+
+ void byteSwap() {
+ sys::swapByteOrder(Major);
+ sys::swapByteOrder(Minor);
+ }
+};
+
+struct Header {
+ uint8_t Magic[4]; // "DXBC"
+ Hash Hash;
+ ContainerVersion Version;
+ uint32_t FileSize;
+ uint32_t PartCount;
+
+ void byteSwap() {
+ Version.byteSwap();
+ sys::swapByteOrder(FileSize);
+ sys::swapByteOrder(PartCount);
+ }
+ // Structure is followed by part offsets: uint32_t PartOffset[PartCount];
+ // The offset is to a PartHeader, which is followed by the Part Data.
+};
+
+/// Use this type to describe the size and type of a DXIL container part.
+struct PartHeader {
+ uint8_t Name[4];
+ uint32_t Size;
+ // Structure is followed directly by part data: uint8_t PartData[PartSize].
+};
+
+} // namespace dxbc
+} // namespace llvm
+
+#endif // LLVM_BINARYFORMAT_DXCONTAINER_H
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
new file mode 100644
index 0000000000000..69a5e28539d6c
--- /dev/null
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -0,0 +1,44 @@
+//===- DXContainer.h - DXContainer file implementation ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DXContainerFile class, which implements the ObjectFile
+// interface for DXContainer files.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_DXCONTAINER_H
+#define LLVM_OBJECT_DXCONTAINER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBufferRef.h"
+
+namespace llvm {
+namespace object {
+class DXContainer {
+private:
+ DXContainer(MemoryBufferRef O);
+
+ MemoryBufferRef Data;
+ dxbc::Header Header;
+
+ Error parseHeader();
+
+public:
+ StringRef getData() const { return Data.getBuffer(); }
+ static Expected<DXContainer> create(MemoryBufferRef Object);
+
+ const dxbc::Header &getHeader() const { return Header; }
+};
+
+} // namespace object
+} // namespace llvm
+
+#endif // LLVM_OBJECT_DXCONTAINERFILE_H
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 082521049439a..ba612e3d95e9b 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMObject
COFFModuleDefinition.cpp
COFFObjectFile.cpp
Decompressor.cpp
+ DXContainer.cpp
ELF.cpp
ELFObjectFile.cpp
Error.cpp
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
new file mode 100644
index 0000000000000..05d7bc6264a4b
--- /dev/null
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -0,0 +1,44 @@
+//===- DXContainer.cpp - DXContainer object file implementation -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/DXContainer.h"
+#include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/Object/Error.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+static Error parseFailed(const Twine &Msg) {
+ return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
+}
+
+template <typename T>
+static Error readStruct(StringRef Buffer, const char *P, T &Struct) {
+ // Don't read before the beginning or past the end of the file
+ if (P < Buffer.begin() || P + sizeof(T) > Buffer.end())
+ return parseFailed("Reading structure out of file bounds");
+
+ memcpy(&Struct, P, sizeof(T));
+ // DXContainer is always BigEndian
+ if (sys::IsBigEndianHost)
+ Struct.byteSwap();
+ return Error::success();
+}
+
+DXContainer::DXContainer(MemoryBufferRef O) : Data(O) {}
+
+Error DXContainer::parseHeader() {
+ return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header);
+}
+
+Expected<DXContainer> DXContainer::create(MemoryBufferRef Object) {
+ DXContainer Container(Object);
+ if (Error Err = Container.parseHeader())
+ return Err;
+ return Container;
+}
diff --git a/llvm/unittests/Object/CMakeLists.txt b/llvm/unittests/Object/CMakeLists.txt
index ea7df2246b4df..d30125d862eb7 100644
--- a/llvm/unittests/Object/CMakeLists.txt
+++ b/llvm/unittests/Object/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(ObjectTests
ArchiveTest.cpp
+ DXContainerTest.cpp
ELFObjectFileTest.cpp
ELFTypesTest.cpp
ELFTest.cpp
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
new file mode 100644
index 0000000000000..846176a089fbc
--- /dev/null
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -0,0 +1,43 @@
+//===- DXContainerTest.cpp - Tests for DXContainerFile --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/DXContainer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/Support/MemoryBufferRef.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+template <std::size_t X> MemoryBufferRef getMemoryBuffer(uint8_t Data[X]) {
+ StringRef Obj(reinterpret_cast<char *>(&Data[0]), X);
+ return MemoryBufferRef(Obj, "");
+}
+
+TEST(DXCFile, ParseHeaderErrors) {
+ uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43};
+ EXPECT_THAT_EXPECTED(
+ DXContainer::create(getMemoryBuffer<4>(Buffer)),
+ FailedWithMessage("Reading structure out of file bounds"));
+}
+
+TEST(DXCFile, ParseHeader) {
+ uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x70, 0x0D, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00};
+ DXContainer C =
+ llvm::cantFail(DXContainer::create(getMemoryBuffer<32>(Buffer)));
+ EXPECT_TRUE(memcmp(C.getHeader().Magic, "DXBC", 4) == 0);
+ EXPECT_TRUE(memcmp(C.getHeader().Hash.Digest,
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0);
+ EXPECT_EQ(C.getHeader().Version.Major, 1u);
+ EXPECT_EQ(C.getHeader().Version.Minor, 0u);
+}
More information about the llvm-commits
mailing list