Skip to content

Commit 3606406

Browse files
committed
[OFFLOAD][L0] Use device ELF as image for L0ProgramTy
1 parent bc0ccaf commit 3606406

File tree

5 files changed

+91
-86
lines changed

5 files changed

+91
-86
lines changed

offload/plugins-nextgen/level_zero/include/L0Device.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,14 @@ class L0DeviceTy final : public GenericDeviceTy {
307307
}
308308

309309
// add a new program to the device. Return a reference to the new program
310-
L0ProgramTy &addProgram(int32_t ImageId,
311-
std::unique_ptr<MemoryBuffer> &&Image) {
312-
Programs.emplace_back(ImageId, *this, std::move(Image));
310+
Expected<L0ProgramTy &> addProgram(int32_t ImageId,
311+
L0ProgramBuilderTy &Builder) {
312+
auto ImageOrErr = Builder.getELF();
313+
if (!ImageOrErr)
314+
return ImageOrErr.takeError();
315+
Programs.emplace_back(ImageId, *this, std::move(*ImageOrErr),
316+
Builder.getGlobalModule(),
317+
std::move(Builder.getModules()));
313318
return Programs.back();
314319
}
315320

offload/plugins-nextgen/level_zero/include/L0Program.h

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,47 @@ struct ProgramDataTy {
3333
int TeamsThreadLimit = 0;
3434
};
3535

36+
class L0ProgramBuilderTy {
37+
L0DeviceTy &Device;
38+
std::unique_ptr<MemoryBuffer> Image;
39+
/// Handle multiple modules within a single target image
40+
llvm::SmallVector<ze_module_handle_t> Modules;
41+
42+
/// Module that contains global data including device RTL
43+
ze_module_handle_t GlobalModule = nullptr;
44+
45+
/// Requires module link
46+
bool RequiresModuleLink = false;
47+
48+
/// Build a single module with the given image, build option, and format.
49+
Error addModule(const size_t Size, const uint8_t *Image,
50+
const std::string_view BuildOption,
51+
ze_module_format_t Format);
52+
53+
Error linkModules();
54+
55+
public:
56+
L0ProgramBuilderTy(L0DeviceTy &Device, std::unique_ptr<MemoryBuffer> &&Image)
57+
: Device(Device), Image(std::move(Image)) {}
58+
~L0ProgramBuilderTy() = default;
59+
60+
L0DeviceTy &getL0Device() const { return Device; }
61+
ze_module_handle_t getGlobalModule() const { return GlobalModule; }
62+
llvm::SmallVector<ze_module_handle_t> &getModules() { return Modules; }
63+
64+
const void *getStart() const { return Image->getBufferStart(); }
65+
size_t getSize() const { return Image->getBufferSize(); }
66+
67+
MemoryBufferRef getMemoryBuffer() const {
68+
return MemoryBufferRef(StringRef((const char *)getStart(), getSize()),
69+
"Image");
70+
}
71+
Error buildModules(const std::string_view BuildOptions);
72+
73+
/// Retrieve the ELF binary for the program
74+
Expected<std::unique_ptr<MemoryBuffer>> getELF();
75+
};
76+
3677
/// Level Zero program that can contain multiple modules.
3778
class L0ProgramTy : public DeviceImageTy {
3879
/// Handle multiple modules within a single target image
@@ -49,32 +90,17 @@ class L0ProgramTy : public DeviceImageTy {
4990
/// Module that contains global data including device RTL
5091
ze_module_handle_t GlobalModule = nullptr;
5192

52-
/// Requires module link
53-
bool RequiresModuleLink = false;
54-
55-
/// Is this module library
56-
bool IsLibModule = false;
57-
58-
/// Build a single module with the given image, build option, and format.
59-
Error addModule(const size_t Size, const uint8_t *Image,
60-
const std::string_view BuildOption,
61-
ze_module_format_t Format);
62-
/// Read file and return the size of the binary if successful.
63-
size_t readFile(const char *FileName, std::vector<uint8_t> &OutFile) const;
64-
void replaceDriverOptsWithBackendOpts(const L0DeviceTy &Device,
65-
std::string &Options) const;
66-
67-
/// Check if the image should be handled as a library module
68-
void setLibModule();
69-
7093
L0DeviceTy &getL0Device() const;
7194

7295
public:
7396
L0ProgramTy() = delete;
7497

7598
L0ProgramTy(int32_t ImageId, GenericDeviceTy &Device,
76-
std::unique_ptr<MemoryBuffer> Image)
77-
: DeviceImageTy(ImageId, Device, std::move(Image)) {}
99+
std::unique_ptr<MemoryBuffer> Image,
100+
ze_module_handle_t GlobalModule,
101+
llvm::SmallVector<ze_module_handle_t> &&Modules)
102+
: DeviceImageTy(ImageId, Device, std::move(Image)),
103+
Modules(std::move(Modules)), GlobalModule(GlobalModule) {}
78104
~L0ProgramTy() {}
79105

80106
L0ProgramTy(const L0ProgramTy &other) = delete;
@@ -88,12 +114,6 @@ class L0ProgramTy : public DeviceImageTy {
88114
return static_cast<L0ProgramTy &>(Device);
89115
}
90116

91-
/// Build modules from the target image description
92-
Error buildModules(const std::string_view BuildOptions);
93-
94-
/// Link modules stored in \p Modules.
95-
Error linkModules();
96-
97117
/// Loads the kernels names from all modules
98118
Error loadModuleKernels();
99119

offload/plugins-nextgen/level_zero/src/L0Device.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,15 @@ L0DeviceTy::loadBinaryImpl(std::unique_ptr<MemoryBuffer> &&TgtImage,
250250

251251
CompilationOptions += " ";
252252
CompilationOptions += Options.InternalCompilationOptions;
253-
auto &Program = addProgram(ImageId, std::move(TgtImage));
254253

255-
if (auto Err = Program.buildModules(CompilationOptions))
254+
L0ProgramBuilderTy Builder(*this, std::move(TgtImage));
255+
if (auto Err = Builder.buildModules(CompilationOptions))
256256
return std::move(Err);
257257

258-
if (auto Err = Program.linkModules())
259-
return std::move(Err);
258+
auto ProgramOrErr = addProgram(ImageId, Builder);
259+
if (!ProgramOrErr)
260+
return ProgramOrErr.takeError();
261+
auto &Program = *ProgramOrErr;
260262

261263
if (auto Err = Program.loadModuleKernels())
262264
return std::move(Err);

offload/plugins-nextgen/level_zero/src/L0DynWrapper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ DLWRAP(zeMemGetAddressRange, 4)
8181
DLWRAP(zeMemGetAllocProperties, 4)
8282
DLWRAP(zeModuleDynamicLink, 3)
8383
DLWRAP(zeModuleGetGlobalPointer, 4)
84+
DLWRAP(zeModuleGetNativeBinary, 3)
8485
DLWRAP(zesDeviceEnumMemoryModules, 3)
8586
DLWRAP(zesMemoryGetState, 2)
8687
DLWRAP(zeCommandListHostSynchronize, 2)

offload/plugins-nextgen/level_zero/src/L0Program.cpp

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -57,42 +57,17 @@ Error L0ProgramTy::deinit() {
5757
return Plugin::success();
5858
}
5959

60-
void L0ProgramTy::setLibModule() {
61-
#if _WIN32
62-
return;
63-
#else
64-
// Check if the image belongs to a dynamic library
65-
Dl_info DLI{nullptr, nullptr, nullptr, nullptr};
66-
if (dladdr(getStart(), &DLI) && DLI.dli_fname) {
67-
std::vector<uint8_t> FileBin;
68-
auto Size = readFile(DLI.dli_fname, FileBin);
69-
if (Size) {
70-
auto MB = MemoryBuffer::getMemBuffer(
71-
StringRef(reinterpret_cast<const char *>(FileBin.data()), Size),
72-
/*BufferName=*/"", /*RequiresNullTerminator=*/false);
73-
auto ELF = ELFObjectFileBase::createELFObjectFile(MB->getMemBufferRef());
74-
if (ELF) {
75-
if (auto *Obj = dyn_cast<ELF64LEObjectFile>((*ELF).get())) {
76-
const auto Header = Obj->getELFFile().getHeader();
77-
if (Header.e_type == ELF::ET_DYN) {
78-
DP("Processing current image as library\n");
79-
IsLibModule = true;
80-
}
81-
}
82-
}
83-
}
84-
}
85-
#endif // _WIN32
86-
}
87-
88-
Error L0ProgramTy::addModule(size_t Size, const uint8_t *Image,
89-
const std::string_view CommonBuildOptions,
90-
ze_module_format_t Format) {
60+
Error L0ProgramBuilderTy::addModule(size_t Size, const uint8_t *Image,
61+
const std::string_view CommonBuildOptions,
62+
ze_module_format_t Format) {
9163
const ze_module_constants_t SpecConstants =
9264
LevelZeroPluginTy::getOptions().CommonSpecConstants.getModuleConstants();
9365
auto &l0Device = getL0Device();
9466
std::string BuildOptions(CommonBuildOptions);
9567

68+
bool IsLibModule =
69+
BuildOptions.find("-library-compilation") != std::string::npos;
70+
9671
// Add required flag to enable dynamic linking.
9772
if (IsLibModule)
9873
BuildOptions += " -library-compilation ";
@@ -128,7 +103,7 @@ Error L0ProgramTy::addModule(size_t Size, const uint8_t *Image,
128103
return Plugin::success();
129104
}
130105

131-
Error L0ProgramTy::linkModules() {
106+
Error L0ProgramBuilderTy::linkModules() {
132107
auto &l0Device = getL0Device();
133108
if (!RequiresModuleLink) {
134109
DP("Module link is not required\n");
@@ -147,24 +122,8 @@ Error L0ProgramTy::linkModules() {
147122
return Plugin::success();
148123
}
149124

150-
size_t L0ProgramTy::readFile(const char *FileName,
151-
std::vector<uint8_t> &OutFile) const {
152-
std::ifstream IFS(FileName, std::ios::binary);
153-
if (!IFS.good())
154-
return 0;
155-
IFS.seekg(0, IFS.end);
156-
auto FileSize = static_cast<size_t>(IFS.tellg());
157-
OutFile.resize(FileSize);
158-
IFS.seekg(0);
159-
if (!IFS.read(reinterpret_cast<char *>(OutFile.data()), FileSize)) {
160-
OutFile.clear();
161-
return 0;
162-
}
163-
return FileSize;
164-
}
165-
166-
void L0ProgramTy::replaceDriverOptsWithBackendOpts(const L0DeviceTy &Device,
167-
std::string &Options) const {
125+
static void replaceDriverOptsWithBackendOpts(const L0DeviceTy &Device,
126+
std::string &Options) {
168127
// Options that need to be replaced with backend-specific options
169128
static const struct {
170129
std::string Option;
@@ -256,7 +215,7 @@ bool isValidOneOmpImage(StringRef Image, uint64_t &MajorVer,
256215
return Res;
257216
}
258217

259-
Error L0ProgramTy::buildModules(const std::string_view BuildOptions) {
218+
Error L0ProgramBuilderTy::buildModules(const std::string_view BuildOptions) {
260219
auto &l0Device = getL0Device();
261220
auto Image = getMemoryBuffer();
262221
if (identify_magic(Image.getBuffer()) == file_magic::spirv_object) {
@@ -272,8 +231,6 @@ Error L0ProgramTy::buildModules(const std::string_view BuildOptions) {
272231
return Plugin::error(ErrorCode::UNKNOWN, "Invalid oneAPI OpenMP image");
273232
}
274233

275-
setLibModule();
276-
277234
// Iterate over the images and pick the first one that fits.
278235
uint64_t ImageCount = 0;
279236
struct V1ImageInfo {
@@ -473,12 +430,32 @@ Error L0ProgramTy::buildModules(const std::string_view BuildOptions) {
473430
}
474431
DP("Created module from image #%" PRIu64 ".\n", Idx);
475432

433+
if (RequiresModuleLink) {
434+
DP("Linking modules after adding image #%" PRIu64 ".\n", Idx);
435+
if (auto Err = linkModules())
436+
return Err;
437+
}
438+
476439
return Plugin::success();
477440
}
478441

479442
return Plugin::error(ErrorCode::UNKNOWN, "Failed to create program modules.");
480443
}
481444

445+
Expected<std::unique_ptr<MemoryBuffer>> L0ProgramBuilderTy::getELF() {
446+
assert(GlobalModule != nullptr && "GlobalModule is null");
447+
448+
size_t Size = 0;
449+
450+
CALL_ZE_RET_ERROR(zeModuleGetNativeBinary, GlobalModule, &Size, nullptr);
451+
std::vector<uint8_t> ELFData(Size);
452+
CALL_ZE_RET_ERROR(zeModuleGetNativeBinary, GlobalModule, &Size,
453+
ELFData.data());
454+
return MemoryBuffer::getMemBufferCopy(
455+
StringRef(reinterpret_cast<const char *>(ELFData.data()), Size),
456+
/*BufferName=*/"L0Program ELF");
457+
}
458+
482459
Expected<void *> L0ProgramTy::getOffloadVarDeviceAddr(const char *CName) const {
483460
DP("Looking up OpenMP global variable '%s'.\n", CName);
484461

0 commit comments

Comments
 (0)