Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / openmp / libomptarget / plugins-nextgen / common / PluginInterface / GlobalHandler.cpp
blobb375d77f2023b02eb68e2c81412528397d0b420a
1 //===- GlobalHandler.cpp - Target independent global & env. var handling --===//
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 // Target independent global handler and environment manager.
11 //===----------------------------------------------------------------------===//
13 #include "GlobalHandler.h"
14 #include "ELFSymbols.h"
15 #include "PluginInterface.h"
16 #include "Utilities.h"
18 #include <cstring>
20 using namespace llvm;
21 using namespace omp;
22 using namespace target;
23 using namespace plugin;
25 const ELF64LEObjectFile *
26 GenericGlobalHandlerTy::getOrCreateELFObjectFile(const GenericDeviceTy &Device,
27 DeviceImageTy &Image) {
29 auto Search = ELFObjectFiles.find(Image.getId());
30 if (Search != ELFObjectFiles.end())
31 // The ELF object file was already there.
32 return &Search->second;
34 // The ELF object file we are checking is not created yet.
35 Expected<ELF64LEObjectFile> ElfOrErr =
36 ELF64LEObjectFile::create(Image.getMemoryBuffer());
37 if (!ElfOrErr) {
38 consumeError(ElfOrErr.takeError());
39 return nullptr;
42 auto Result =
43 ELFObjectFiles.try_emplace(Image.getId(), std::move(ElfOrErr.get()));
44 assert(Result.second && "Map insertion failed");
45 assert(Result.first != ELFObjectFiles.end() && "Map insertion failed");
47 return &Result.first->second;
50 Error GenericGlobalHandlerTy::getGlobalMetadataFromELF(
51 const DeviceImageTy &Image, const ELF64LE::Sym &Symbol,
52 const ELF64LE::Shdr &Section, GlobalTy &ImageGlobal) {
54 // The global's address is computed as the image begin + the ELF section
55 // offset + the ELF symbol value.
56 ImageGlobal.setPtr(advanceVoidPtr(
57 Image.getStart(), Section.sh_offset - Section.sh_addr + Symbol.st_value));
59 // Set the global's size.
60 ImageGlobal.setSize(Symbol.st_size);
62 return Plugin::success();
65 Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
66 GenericDeviceTy &Device, DeviceImageTy &Image, const GlobalTy &HostGlobal,
67 bool Device2Host) {
69 GlobalTy DeviceGlobal(HostGlobal.getName(), HostGlobal.getSize());
71 // Get the metadata from the global on the device.
72 if (auto Err = getGlobalMetadataFromDevice(Device, Image, DeviceGlobal))
73 return Err;
75 // Perform the actual transfer.
76 return moveGlobalBetweenDeviceAndHost(Device, HostGlobal, DeviceGlobal,
77 Device2Host);
80 /// Actually move memory between host and device. See readGlobalFromDevice and
81 /// writeGlobalToDevice for the interface description.
82 Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
83 GenericDeviceTy &Device, const GlobalTy &HostGlobal,
84 const GlobalTy &DeviceGlobal, bool Device2Host) {
86 // Transfer the data from the source to the destination.
87 if (Device2Host) {
88 if (auto Err =
89 Device.dataRetrieve(HostGlobal.getPtr(), DeviceGlobal.getPtr(),
90 HostGlobal.getSize(), nullptr))
91 return Err;
92 } else {
93 if (auto Err = Device.dataSubmit(DeviceGlobal.getPtr(), HostGlobal.getPtr(),
94 HostGlobal.getSize(), nullptr))
95 return Err;
98 DP("Succesfully %s %u bytes associated with global symbol '%s' %s the device "
99 "(%p -> %p).\n",
100 Device2Host ? "read" : "write", HostGlobal.getSize(),
101 HostGlobal.getName().data(), Device2Host ? "from" : "to",
102 DeviceGlobal.getPtr(), HostGlobal.getPtr());
104 return Plugin::success();
107 Error GenericGlobalHandlerTy::getGlobalMetadataFromImage(
108 GenericDeviceTy &Device, DeviceImageTy &Image, GlobalTy &ImageGlobal) {
110 // Get the ELF object file for the image. Notice the ELF object may already
111 // be created in previous calls, so we can reuse it.
112 const ELF64LEObjectFile *ELFObj = getOrCreateELFObjectFile(Device, Image);
113 if (!ELFObj)
114 return Plugin::error("Unable to create ELF object for image %p",
115 Image.getStart());
117 // Search the ELF symbol using the symbol name.
118 auto SymOrErr = getELFSymbol(*ELFObj, ImageGlobal.getName());
119 if (!SymOrErr)
120 return Plugin::error("Failed ELF lookup of global '%s': %s",
121 ImageGlobal.getName().data(),
122 toString(SymOrErr.takeError()).data());
124 if (!*SymOrErr)
125 return Plugin::error("Failed to find global symbol '%s' in the ELF image",
126 ImageGlobal.getName().data());
128 // Get the section to which the symbol belongs.
129 auto SecOrErr = ELFObj->getELFFile().getSection((*SymOrErr)->st_shndx);
130 if (!SecOrErr)
131 return Plugin::error("Failed to get ELF section from global '%s': %s",
132 ImageGlobal.getName().data(),
133 toString(SecOrErr.takeError()).data());
135 // Setup the global symbol's address and size.
136 return getGlobalMetadataFromELF(Image, **SymOrErr, **SecOrErr, ImageGlobal);
139 Error GenericGlobalHandlerTy::readGlobalFromImage(GenericDeviceTy &Device,
140 DeviceImageTy &Image,
141 const GlobalTy &HostGlobal) {
143 GlobalTy ImageGlobal(HostGlobal.getName(), -1);
144 if (auto Err = getGlobalMetadataFromImage(Device, Image, ImageGlobal))
145 return Err;
147 if (ImageGlobal.getSize() != HostGlobal.getSize())
148 return Plugin::error("Transfer failed because global symbol '%s' has "
149 "%u bytes in the ELF image but %u bytes on the host",
150 HostGlobal.getName().data(), ImageGlobal.getSize(),
151 HostGlobal.getSize());
153 DP("Global symbol '%s' was found in the ELF image and %u bytes will copied "
154 "from %p to %p.\n",
155 HostGlobal.getName().data(), HostGlobal.getSize(), ImageGlobal.getPtr(),
156 HostGlobal.getPtr());
158 // Perform the copy from the image to the host memory.
159 std::memcpy(HostGlobal.getPtr(), ImageGlobal.getPtr(), HostGlobal.getSize());
161 return Plugin::success();