Skip to content

Commit 15babba

Browse files
authored
[DirectX] Add boilerplate integration of objcopy for DXContainerObjectFile (#153079)
This pr implements the boiler plate required to use `llvm-objcopy` for `DXContainer` object files. It defines a minimal structure `object` to represent the `DXContainer` header and the following parts. This structure is a simple representation of the object data to allow for simple modifications at the granularity of each part. It follows similarily to how the respective `object`s are defined for `ELF`, `wasm`, `XCOFF`, etc. This is the first step to implement #150275 and #150277 as compiler actions that invoke `llvm-objcopy` for functionality.
1 parent d76bb2b commit 15babba

17 files changed

+755
-0
lines changed

llvm/include/llvm/ObjCopy/ConfigManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "llvm/ObjCopy/COFF/COFFConfig.h"
1313
#include "llvm/ObjCopy/CommonConfig.h"
14+
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
1415
#include "llvm/ObjCopy/ELF/ELFConfig.h"
1516
#include "llvm/ObjCopy/MachO/MachOConfig.h"
1617
#include "llvm/ObjCopy/MultiFormatConfig.h"
@@ -36,13 +37,16 @@ struct LLVM_ABI ConfigManager : public MultiFormatConfig {
3637

3738
Expected<const XCOFFConfig &> getXCOFFConfig() const override;
3839

40+
Expected<const DXContainerConfig &> getDXContainerConfig() const override;
41+
3942
// All configs.
4043
CommonConfig Common;
4144
ELFConfig ELF;
4245
COFFConfig COFF;
4346
MachOConfig MachO;
4447
WasmConfig Wasm;
4548
XCOFFConfig XCOFF;
49+
DXContainerConfig DXContainer;
4650
};
4751

4852
} // namespace objcopy
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===- DXContainerConfig.h --------------------------------------*- 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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H
10+
#define LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H
11+
12+
namespace llvm {
13+
namespace objcopy {
14+
15+
// DXContainer specific configuration for copying/stripping a single file. This
16+
// is defined, following convention elsewhere, as the return type of
17+
// `getDXContainerConfig`, which reports an error for an unsupported option.
18+
struct DXContainerConfig {};
19+
20+
} // namespace objcopy
21+
} // namespace llvm
22+
23+
#endif // LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===- DXContainerObjcopy.h -------------------------------------*- 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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H
10+
#define LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H
11+
12+
namespace llvm {
13+
class Error;
14+
class raw_ostream;
15+
16+
namespace object {
17+
class DXContainerObjectFile;
18+
} // end namespace object
19+
20+
namespace objcopy {
21+
struct CommonConfig;
22+
struct DXContainerConfig;
23+
24+
namespace dxbc {
25+
/// Apply the transformations described by \p Config and \p DXContainerConfig
26+
/// to \p In and writes the result into \p Out.
27+
/// \returns any Error encountered whilst performing the operation.
28+
Error executeObjcopyOnBinary(const CommonConfig &Config,
29+
const DXContainerConfig &,
30+
object::DXContainerObjectFile &In,
31+
raw_ostream &Out);
32+
} // end namespace dxbc
33+
} // end namespace objcopy
34+
} // end namespace llvm
35+
36+
#endif // LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H

llvm/include/llvm/ObjCopy/MultiFormatConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct COFFConfig;
2020
struct MachOConfig;
2121
struct WasmConfig;
2222
struct XCOFFConfig;
23+
struct DXContainerConfig;
2324

2425
class MultiFormatConfig {
2526
public:
@@ -31,6 +32,7 @@ class MultiFormatConfig {
3132
virtual Expected<const MachOConfig &> getMachOConfig() const = 0;
3233
virtual Expected<const WasmConfig &> getWasmConfig() const = 0;
3334
virtual Expected<const XCOFFConfig &> getXCOFFConfig() const = 0;
35+
virtual Expected<const DXContainerConfig &> getDXContainerConfig() const = 0;
3436
};
3537

3638
} // namespace objcopy

llvm/include/llvm/Object/DXContainer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,8 @@ class LLVM_ABI DXContainerObjectFile : public ObjectFile {
607607

608608
static bool classof(const Binary *v) { return v->isDXContainer(); }
609609

610+
const dxbc::Header &getHeader() const { return Container.getHeader(); }
611+
610612
Expected<StringRef> getSymbolName(DataRefImpl) const override;
611613
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
612614
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;

llvm/lib/ObjCopy/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ source_group("Header Files\\wasm" REGULAR_EXPRESSION
1616
source_group("Header Files\\XCOFF" REGULAR_EXPRESSION
1717
XCOFF/.*[.]h
1818
)
19+
source_group("Header Files\\DXContainer" REGULAR_EXPRESSION
20+
DXContainer/.*[.]h
21+
)
1922
source_group("Source Files" REGULAR_EXPRESSION
2023
.*[.]cpp
2124
)
@@ -34,9 +37,15 @@ source_group("Source Files\\wasm" REGULAR_EXPRESSION
3437
source_group("Source Files\\XCOFF" REGULAR_EXPRESSION
3538
XCOFF/.*[.]cpp
3639
)
40+
source_group("Source Files\\DXContainer" REGULAR_EXPRESSION
41+
DXContainer/.*[.]cpp
42+
)
3743

3844
add_llvm_component_library(LLVMObjCopy
3945
Archive.cpp
46+
DXContainer/DXContainerObjcopy.cpp
47+
DXContainer/DXContainerReader.cpp
48+
DXContainer/DXContainerWriter.cpp
4049
CommonConfig.cpp
4150
ObjCopy.cpp
4251
ConfigManager.cpp
@@ -62,11 +71,13 @@ add_llvm_component_library(LLVMObjCopy
6271
ADDITIONAL_HEADER_DIRS
6372
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy
6473
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/COFF
74+
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/DXContainer
6575
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/ELF
6676
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/MachO
6777
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/wasm
6878
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/XCOFF
6979
COFF
80+
DXContainer
7081
ELF
7182
MachO
7283
wasm

llvm/lib/ObjCopy/ConfigManager.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,27 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
107107

108108
return XCOFF;
109109
}
110+
111+
Expected<const DXContainerConfig &>
112+
ConfigManager::getDXContainerConfig() const {
113+
// All other flags are either supported or not applicable for DXContainer
114+
// object files and will be silently ignored.
115+
if (!Common.AddGnuDebugLink.empty() || !Common.SplitDWO.empty() ||
116+
!Common.AllocSectionsPrefix.empty() ||
117+
Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
118+
!Common.DumpSection.empty() || !Common.KeepSection.empty() ||
119+
!Common.OnlySection.empty() || !Common.ToRemove.empty() ||
120+
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
121+
!Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
122+
Common.ExtractDWO || Common.OnlyKeepDebug || Common.StripAllGNU ||
123+
Common.StripDWO || Common.StripDebug || Common.StripNonAlloc ||
124+
Common.StripSections || Common.StripUnneeded ||
125+
Common.DecompressDebugSections || Common.GapFill != 0 ||
126+
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
127+
!Common.ChangeSectionAddress.empty()) {
128+
return createStringError(
129+
llvm::errc::invalid_argument,
130+
"no flags are supported yet, only basic copying is allowed");
131+
}
132+
return DXContainer;
133+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===- DXContainerObjcopy.cpp ---------------------------------------------===//
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+
9+
#include "llvm/ObjCopy/DXContainer/DXContainerObjcopy.h"
10+
#include "DXContainerReader.h"
11+
#include "DXContainerWriter.h"
12+
#include "llvm/ObjCopy/CommonConfig.h"
13+
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
14+
15+
namespace llvm {
16+
namespace objcopy {
17+
namespace dxbc {
18+
19+
using namespace object;
20+
21+
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
22+
return Error::success();
23+
}
24+
25+
Error executeObjcopyOnBinary(const CommonConfig &Config,
26+
const DXContainerConfig &,
27+
DXContainerObjectFile &In, raw_ostream &Out) {
28+
DXContainerReader Reader(In);
29+
Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
30+
if (!ObjOrErr)
31+
return createFileError(Config.InputFilename, ObjOrErr.takeError());
32+
Object *Obj = ObjOrErr->get();
33+
assert(Obj && "Unable to deserialize DXContainer object");
34+
35+
if (Error E = handleArgs(Config, *Obj))
36+
return E;
37+
38+
DXContainerWriter Writer(*Obj, Out);
39+
if (Error E = Writer.write())
40+
return createFileError(Config.OutputFilename, std::move(E));
41+
return Error::success();
42+
}
43+
44+
} // end namespace dxbc
45+
} // end namespace objcopy
46+
} // end namespace llvm
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===- DXContainerObject.h --------------------------------------*- 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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINEROBJECT_H
10+
#define LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINEROBJECT_H
11+
12+
#include "llvm/ADT/ArrayRef.h"
13+
#include "llvm/ADT/StringRef.h"
14+
#include "llvm/Object/DXContainer.h"
15+
#include <vector>
16+
17+
namespace llvm {
18+
namespace objcopy {
19+
namespace dxbc {
20+
21+
using namespace object;
22+
23+
struct Part {
24+
StringRef Name;
25+
ArrayRef<uint8_t> Data;
26+
27+
size_t size() const {
28+
return sizeof(::llvm::dxbc::PartHeader) // base header
29+
+ Data.size(); // contents size
30+
}
31+
};
32+
33+
struct Object {
34+
::llvm::dxbc::Header Header;
35+
SmallVector<Part> Parts;
36+
37+
size_t headerSize() const {
38+
return sizeof(::llvm::dxbc::Header) // base header
39+
+ sizeof(uint32_t) * Parts.size(); // part offset values
40+
}
41+
};
42+
43+
} // end namespace dxbc
44+
} // end namespace objcopy
45+
} // end namespace llvm
46+
47+
#endif // LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINEROBJECT_H
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===- DXContainerReader.cpp ----------------------------------------------===//
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+
9+
#include "DXContainerReader.h"
10+
11+
namespace llvm {
12+
namespace objcopy {
13+
namespace dxbc {
14+
15+
using namespace object;
16+
17+
Expected<std::unique_ptr<Object>> DXContainerReader::create() const {
18+
auto Obj = std::make_unique<Object>();
19+
Obj->Header = DXContainerObj.getHeader();
20+
for (const SectionRef &Part : DXContainerObj.sections()) {
21+
DataRefImpl PartDRI = Part.getRawDataRefImpl();
22+
Expected<StringRef> Name = DXContainerObj.getSectionName(PartDRI);
23+
if (auto E = Name.takeError())
24+
return E;
25+
assert(Name->size() == 4 &&
26+
"Valid DXIL Part name consists of 4 characters");
27+
Expected<ArrayRef<uint8_t>> Data =
28+
DXContainerObj.getSectionContents(PartDRI);
29+
if (auto E = Data.takeError())
30+
return E;
31+
Obj->Parts.push_back({*Name, *Data});
32+
}
33+
return std::move(Obj);
34+
}
35+
36+
} // end namespace dxbc
37+
} // end namespace objcopy
38+
} // end namespace llvm

0 commit comments

Comments
 (0)