1ec8f4a38SAtmn Patel //===---------------- Utils.cpp - Utilities for Remote RTL ----------------===//
2ec8f4a38SAtmn Patel //
3ec8f4a38SAtmn Patel // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ec8f4a38SAtmn Patel // See https://llvm.org/LICENSE.txt for license information.
5ec8f4a38SAtmn Patel // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec8f4a38SAtmn Patel //
7ec8f4a38SAtmn Patel //===----------------------------------------------------------------------===//
8ec8f4a38SAtmn Patel //
9ec8f4a38SAtmn Patel // Utilities for data movement and debugging.
10ec8f4a38SAtmn Patel //
11ec8f4a38SAtmn Patel //===----------------------------------------------------------------------===//
12ec8f4a38SAtmn Patel 
13ec8f4a38SAtmn Patel #include "Utils.h"
14ec8f4a38SAtmn Patel #include "omptarget.h"
15ec8f4a38SAtmn Patel 
16ec8f4a38SAtmn Patel namespace RemoteOffloading {
17ec8f4a38SAtmn Patel 
loadTargetBinaryDescription(const __tgt_bin_desc * Desc,TargetBinaryDescription & Request)18ec8f4a38SAtmn Patel void loadTargetBinaryDescription(const __tgt_bin_desc *Desc,
19ec8f4a38SAtmn Patel                                  TargetBinaryDescription &Request) {
20ec8f4a38SAtmn Patel   // Keeps track of entries which have already been deep copied.
21ec8f4a38SAtmn Patel   std::vector<void *> DeepCopiedEntryAddrs;
22ec8f4a38SAtmn Patel 
23ec8f4a38SAtmn Patel   // Copy Global Offload Entries
24ec8f4a38SAtmn Patel   for (auto *CurEntry = Desc->HostEntriesBegin;
25ec8f4a38SAtmn Patel        CurEntry != Desc->HostEntriesEnd; CurEntry++) {
26ec8f4a38SAtmn Patel     auto *NewEntry = Request.add_entries();
27ec8f4a38SAtmn Patel     copyOffloadEntry(CurEntry, NewEntry);
28ec8f4a38SAtmn Patel 
29ec8f4a38SAtmn Patel     // Copy the pointer of the offload entry of the image into the Request
30ec8f4a38SAtmn Patel     Request.add_entry_ptrs((uint64_t)CurEntry);
31ec8f4a38SAtmn Patel     DeepCopiedEntryAddrs.push_back(CurEntry);
32ec8f4a38SAtmn Patel   }
33ec8f4a38SAtmn Patel 
34ec8f4a38SAtmn Patel   // Copy Device Images and Device Offload Entries
35ec8f4a38SAtmn Patel   __tgt_device_image *CurImage = Desc->DeviceImages;
36ec8f4a38SAtmn Patel   for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++) {
37ec8f4a38SAtmn Patel     auto *Image = Request.add_images();
38ec8f4a38SAtmn Patel     auto Size = (char *)CurImage->ImageEnd - (char *)CurImage->ImageStart;
39ec8f4a38SAtmn Patel     Image->set_binary(CurImage->ImageStart, Size);
40ec8f4a38SAtmn Patel 
41ec8f4a38SAtmn Patel     // Copy the pointer of the image into the Request
42ec8f4a38SAtmn Patel     auto *NewImagePtr = Request.add_image_ptrs();
43ec8f4a38SAtmn Patel     NewImagePtr->set_img_ptr((uint64_t)CurImage->ImageStart);
44ec8f4a38SAtmn Patel 
45ec8f4a38SAtmn Patel     // Copy Device Offload Entries
46ec8f4a38SAtmn Patel     for (auto *CurEntry = CurImage->EntriesBegin;
47ec8f4a38SAtmn Patel          CurEntry != CurImage->EntriesEnd; CurEntry++) {
48ec8f4a38SAtmn Patel       auto *NewEntry = Image->add_entries();
49ec8f4a38SAtmn Patel 
50ec8f4a38SAtmn Patel       auto Entry = std::find(DeepCopiedEntryAddrs.begin(),
51ec8f4a38SAtmn Patel                              DeepCopiedEntryAddrs.end(), CurEntry);
52ec8f4a38SAtmn Patel       if (Entry != DeepCopiedEntryAddrs.end()) {
53ec8f4a38SAtmn Patel         // Offload entry has already been loaded
54ec8f4a38SAtmn Patel         shallowCopyOffloadEntry(CurEntry, NewEntry);
55ec8f4a38SAtmn Patel       } else { // Offload Entry has not been loaded into the Request
56ec8f4a38SAtmn Patel         copyOffloadEntry(CurEntry, NewEntry);
57ec8f4a38SAtmn Patel         DeepCopiedEntryAddrs.push_back(CurEntry);
58ec8f4a38SAtmn Patel       }
59ec8f4a38SAtmn Patel 
60ec8f4a38SAtmn Patel       // Copy the pointer of the offload entry of the image into the Request
61ec8f4a38SAtmn Patel       NewImagePtr->add_entry_ptrs((uint64_t)CurEntry);
62ec8f4a38SAtmn Patel     }
63ec8f4a38SAtmn Patel   }
64ec8f4a38SAtmn Patel }
65ec8f4a38SAtmn Patel 
unloadTargetBinaryDescription(const TargetBinaryDescription * Request,__tgt_bin_desc * Desc,std::unordered_map<const void *,__tgt_device_image * > & HostToRemoteDeviceImage)66ec8f4a38SAtmn Patel void unloadTargetBinaryDescription(
67ec8f4a38SAtmn Patel     const TargetBinaryDescription *Request, __tgt_bin_desc *Desc,
68ec8f4a38SAtmn Patel     std::unordered_map<const void *, __tgt_device_image *>
69ec8f4a38SAtmn Patel         &HostToRemoteDeviceImage) {
70ec8f4a38SAtmn Patel   std::unordered_map<const void *, __tgt_offload_entry *> CopiedOffloadEntries;
71ec8f4a38SAtmn Patel   Desc->NumDeviceImages = Request->images_size();
72ec8f4a38SAtmn Patel   Desc->DeviceImages = new __tgt_device_image[Desc->NumDeviceImages];
73ec8f4a38SAtmn Patel 
74ec8f4a38SAtmn Patel   if (Request->entries_size())
75ec8f4a38SAtmn Patel     Desc->HostEntriesBegin = new __tgt_offload_entry[Request->entries_size()];
76ec8f4a38SAtmn Patel   else {
77ec8f4a38SAtmn Patel     Desc->HostEntriesBegin = nullptr;
78ec8f4a38SAtmn Patel     Desc->HostEntriesEnd = nullptr;
79ec8f4a38SAtmn Patel   }
80ec8f4a38SAtmn Patel 
81ec8f4a38SAtmn Patel   // Copy Global Offload Entries
82ec8f4a38SAtmn Patel   __tgt_offload_entry *CurEntry = Desc->HostEntriesBegin;
83*21e92612SAtmn Patel   size_t I = 0;
84*21e92612SAtmn Patel   for (auto &Entry : Request->entries()) {
85*21e92612SAtmn Patel     copyOffloadEntry(Entry, CurEntry);
86*21e92612SAtmn Patel     CopiedOffloadEntries[(void *)Request->entry_ptrs()[I]] = CurEntry;
87ec8f4a38SAtmn Patel     CurEntry++;
88*21e92612SAtmn Patel     I++;
89ec8f4a38SAtmn Patel   }
90ec8f4a38SAtmn Patel   Desc->HostEntriesEnd = CurEntry;
91ec8f4a38SAtmn Patel 
92ec8f4a38SAtmn Patel   // Copy Device Images and Device Offload Entries
93ec8f4a38SAtmn Patel   __tgt_device_image *CurImage = Desc->DeviceImages;
94ec8f4a38SAtmn Patel   auto ImageItr = Request->image_ptrs().begin();
95ec8f4a38SAtmn Patel   for (auto Image : Request->images()) {
96ec8f4a38SAtmn Patel     // Copy Device Offload Entries
97*21e92612SAtmn Patel     CurEntry = Desc->HostEntriesBegin;
98ec8f4a38SAtmn Patel     bool Found = false;
99ec8f4a38SAtmn Patel 
100ec8f4a38SAtmn Patel     if (!Desc->HostEntriesBegin) {
101ec8f4a38SAtmn Patel       CurImage->EntriesBegin = nullptr;
102ec8f4a38SAtmn Patel       CurImage->EntriesEnd = nullptr;
103ec8f4a38SAtmn Patel     }
104ec8f4a38SAtmn Patel 
105*21e92612SAtmn Patel     for (size_t I = 0; I < Image.entries_size(); I++) {
106ec8f4a38SAtmn Patel       auto TgtEntry =
107*21e92612SAtmn Patel           CopiedOffloadEntries.find((void *)Request->entry_ptrs()[I]);
108ec8f4a38SAtmn Patel       if (TgtEntry != CopiedOffloadEntries.end()) {
109ec8f4a38SAtmn Patel         if (!Found)
110ec8f4a38SAtmn Patel           CurImage->EntriesBegin = CurEntry;
111ec8f4a38SAtmn Patel 
112ec8f4a38SAtmn Patel         CurImage->EntriesEnd = CurEntry + 1;
113*21e92612SAtmn Patel         Found = true;
114ec8f4a38SAtmn Patel       } else {
115ec8f4a38SAtmn Patel         Found = false;
116*21e92612SAtmn Patel         copyOffloadEntry(Image.entries()[I], CurEntry);
117*21e92612SAtmn Patel         CopiedOffloadEntries[(void *)(Request->entry_ptrs()[I])] = CurEntry;
118ec8f4a38SAtmn Patel       }
119ec8f4a38SAtmn Patel       CurEntry++;
120ec8f4a38SAtmn Patel     }
121ec8f4a38SAtmn Patel 
122ec8f4a38SAtmn Patel     // Copy Device Image
123ec8f4a38SAtmn Patel     CurImage->ImageStart = new uint8_t[Image.binary().size()];
124ec8f4a38SAtmn Patel     memcpy(CurImage->ImageStart,
125ec8f4a38SAtmn Patel            static_cast<const void *>(Image.binary().data()),
126ec8f4a38SAtmn Patel            Image.binary().size());
127ec8f4a38SAtmn Patel     CurImage->ImageEnd =
128ec8f4a38SAtmn Patel         (void *)((char *)CurImage->ImageStart + Image.binary().size());
129ec8f4a38SAtmn Patel 
130ec8f4a38SAtmn Patel     HostToRemoteDeviceImage[(void *)ImageItr->img_ptr()] = CurImage;
131ec8f4a38SAtmn Patel     CurImage++;
132ec8f4a38SAtmn Patel     ImageItr++;
133ec8f4a38SAtmn Patel   }
134ec8f4a38SAtmn Patel }
135ec8f4a38SAtmn Patel 
freeTargetBinaryDescription(__tgt_bin_desc * Desc)136ec8f4a38SAtmn Patel void freeTargetBinaryDescription(__tgt_bin_desc *Desc) {
137ec8f4a38SAtmn Patel   __tgt_device_image *CurImage = Desc->DeviceImages;
138ec8f4a38SAtmn Patel   for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++)
139ec8f4a38SAtmn Patel     delete[](uint64_t *) CurImage->ImageStart;
140ec8f4a38SAtmn Patel 
141ec8f4a38SAtmn Patel   delete[] Desc->DeviceImages;
142ec8f4a38SAtmn Patel 
143ec8f4a38SAtmn Patel   for (auto *Entry = Desc->HostEntriesBegin; Entry != Desc->HostEntriesEnd;
144ec8f4a38SAtmn Patel        Entry++) {
145ec8f4a38SAtmn Patel     free(Entry->name);
146ec8f4a38SAtmn Patel     free(Entry->addr);
147ec8f4a38SAtmn Patel   }
148ec8f4a38SAtmn Patel 
149ec8f4a38SAtmn Patel   delete[] Desc->HostEntriesBegin;
150ec8f4a38SAtmn Patel }
151ec8f4a38SAtmn Patel 
freeTargetTable(__tgt_target_table * Table)152ec8f4a38SAtmn Patel void freeTargetTable(__tgt_target_table *Table) {
153ec8f4a38SAtmn Patel   for (auto *Entry = Table->EntriesBegin; Entry != Table->EntriesEnd; Entry++)
154ec8f4a38SAtmn Patel     free(Entry->name);
155ec8f4a38SAtmn Patel 
156ec8f4a38SAtmn Patel   delete[] Table->EntriesBegin;
157ec8f4a38SAtmn Patel }
158ec8f4a38SAtmn Patel 
loadTargetTable(__tgt_target_table * Table,TargetTable & TableResponse,__tgt_device_image * Image)159ec8f4a38SAtmn Patel void loadTargetTable(__tgt_target_table *Table, TargetTable &TableResponse,
160ec8f4a38SAtmn Patel                      __tgt_device_image *Image) {
161ec8f4a38SAtmn Patel   auto *ImageEntry = Image->EntriesBegin;
162ec8f4a38SAtmn Patel   for (__tgt_offload_entry *CurEntry = Table->EntriesBegin;
163ec8f4a38SAtmn Patel        CurEntry != Table->EntriesEnd; CurEntry++, ImageEntry++) {
164ec8f4a38SAtmn Patel     // TODO: This can probably be trimmed substantially.
165ec8f4a38SAtmn Patel     auto *NewEntry = TableResponse.add_entries();
166ec8f4a38SAtmn Patel     NewEntry->set_name(CurEntry->name);
167ec8f4a38SAtmn Patel     NewEntry->set_addr((uint64_t)CurEntry->addr);
168ec8f4a38SAtmn Patel     NewEntry->set_flags(CurEntry->flags);
169ec8f4a38SAtmn Patel     NewEntry->set_reserved(CurEntry->reserved);
170ec8f4a38SAtmn Patel     NewEntry->set_size(CurEntry->size);
171ec8f4a38SAtmn Patel     TableResponse.add_entry_ptrs((int64_t)CurEntry);
172ec8f4a38SAtmn Patel   }
173ec8f4a38SAtmn Patel }
174ec8f4a38SAtmn Patel 
unloadTargetTable(TargetTable & TableResponse,__tgt_target_table * Table,std::unordered_map<void *,void * > & HostToRemoteTargetTableMap)175ec8f4a38SAtmn Patel void unloadTargetTable(
176ec8f4a38SAtmn Patel     TargetTable &TableResponse, __tgt_target_table *Table,
177ec8f4a38SAtmn Patel     std::unordered_map<void *, void *> &HostToRemoteTargetTableMap) {
178ec8f4a38SAtmn Patel   Table->EntriesBegin = new __tgt_offload_entry[TableResponse.entries_size()];
179ec8f4a38SAtmn Patel 
180ec8f4a38SAtmn Patel   auto *CurEntry = Table->EntriesBegin;
181*21e92612SAtmn Patel   for (size_t I = 0; I < TableResponse.entries_size(); I++) {
182*21e92612SAtmn Patel     copyOffloadEntry(TableResponse.entries()[I], CurEntry);
183ec8f4a38SAtmn Patel     HostToRemoteTargetTableMap[CurEntry->addr] =
184*21e92612SAtmn Patel         (void *)TableResponse.entry_ptrs()[I];
185ec8f4a38SAtmn Patel     CurEntry++;
186ec8f4a38SAtmn Patel   }
187ec8f4a38SAtmn Patel   Table->EntriesEnd = CurEntry;
188ec8f4a38SAtmn Patel }
189ec8f4a38SAtmn Patel 
copyOffloadEntry(const TargetOffloadEntry & EntryResponse,__tgt_offload_entry * Entry)190ec8f4a38SAtmn Patel void copyOffloadEntry(const TargetOffloadEntry &EntryResponse,
191ec8f4a38SAtmn Patel                       __tgt_offload_entry *Entry) {
192ec8f4a38SAtmn Patel   Entry->name = strdup(EntryResponse.name().c_str());
193ec8f4a38SAtmn Patel   Entry->reserved = EntryResponse.reserved();
194ec8f4a38SAtmn Patel   Entry->flags = EntryResponse.flags();
195ec8f4a38SAtmn Patel   Entry->addr = strdup(EntryResponse.data().c_str());
196ec8f4a38SAtmn Patel   Entry->size = EntryResponse.data().size();
197ec8f4a38SAtmn Patel }
198ec8f4a38SAtmn Patel 
copyOffloadEntry(const DeviceOffloadEntry & EntryResponse,__tgt_offload_entry * Entry)199ec8f4a38SAtmn Patel void copyOffloadEntry(const DeviceOffloadEntry &EntryResponse,
200ec8f4a38SAtmn Patel                       __tgt_offload_entry *Entry) {
201ec8f4a38SAtmn Patel   Entry->name = strdup(EntryResponse.name().c_str());
202ec8f4a38SAtmn Patel   Entry->reserved = EntryResponse.reserved();
203ec8f4a38SAtmn Patel   Entry->flags = EntryResponse.flags();
204ec8f4a38SAtmn Patel   Entry->addr = (void *)EntryResponse.addr();
205ec8f4a38SAtmn Patel   Entry->size = EntryResponse.size();
206ec8f4a38SAtmn Patel }
207ec8f4a38SAtmn Patel 
208ec8f4a38SAtmn Patel /// We shallow copy with just the name because it is a convenient identifier, we
209ec8f4a38SAtmn Patel /// do actually just match off of the address.
shallowCopyOffloadEntry(const __tgt_offload_entry * Entry,TargetOffloadEntry * EntryResponse)210ec8f4a38SAtmn Patel void shallowCopyOffloadEntry(const __tgt_offload_entry *Entry,
211ec8f4a38SAtmn Patel                              TargetOffloadEntry *EntryResponse) {
212ec8f4a38SAtmn Patel   EntryResponse->set_name(Entry->name);
213ec8f4a38SAtmn Patel }
214ec8f4a38SAtmn Patel 
copyOffloadEntry(const __tgt_offload_entry * Entry,TargetOffloadEntry * EntryResponse)215ec8f4a38SAtmn Patel void copyOffloadEntry(const __tgt_offload_entry *Entry,
216ec8f4a38SAtmn Patel                       TargetOffloadEntry *EntryResponse) {
217ec8f4a38SAtmn Patel   shallowCopyOffloadEntry(Entry, EntryResponse);
218ec8f4a38SAtmn Patel   EntryResponse->set_reserved(Entry->reserved);
219ec8f4a38SAtmn Patel   EntryResponse->set_flags(Entry->flags);
220ec8f4a38SAtmn Patel   EntryResponse->set_data(Entry->addr, Entry->size);
221ec8f4a38SAtmn Patel }
222ec8f4a38SAtmn Patel 
223ec8f4a38SAtmn Patel /// Dumps the memory region from Start to End in order to debug memory transfer
224ec8f4a38SAtmn Patel /// errors within the plugin
dump(const void * Start,const void * End)225ec8f4a38SAtmn Patel void dump(const void *Start, const void *End) {
226ec8f4a38SAtmn Patel   unsigned char Line[17];
227ec8f4a38SAtmn Patel   const unsigned char *PrintCharacter = (const unsigned char *)Start;
228ec8f4a38SAtmn Patel 
229ec8f4a38SAtmn Patel   unsigned int I = 0;
230ec8f4a38SAtmn Patel   for (; I < ((const int *)End - (const int *)Start); I++) {
231ec8f4a38SAtmn Patel     if ((I % 16) == 0) {
232ec8f4a38SAtmn Patel       if (I != 0)
233ec8f4a38SAtmn Patel         printf("  %s\n", Line);
234ec8f4a38SAtmn Patel 
235ec8f4a38SAtmn Patel       printf("  %04x ", I);
236ec8f4a38SAtmn Patel     }
237ec8f4a38SAtmn Patel 
238ec8f4a38SAtmn Patel     printf(" %02x", PrintCharacter[I]);
239ec8f4a38SAtmn Patel 
240ec8f4a38SAtmn Patel     if ((PrintCharacter[I] < 0x20) || (PrintCharacter[I] > 0x7e))
241ec8f4a38SAtmn Patel       Line[I % 16] = '.';
242ec8f4a38SAtmn Patel     else
243ec8f4a38SAtmn Patel       Line[I % 16] = PrintCharacter[I];
244ec8f4a38SAtmn Patel 
245ec8f4a38SAtmn Patel     Line[(I % 16) + 1] = '\0';
246ec8f4a38SAtmn Patel   }
247ec8f4a38SAtmn Patel 
248ec8f4a38SAtmn Patel   while ((I % 16) != 0) {
249ec8f4a38SAtmn Patel     printf("   ");
250ec8f4a38SAtmn Patel     I++;
251ec8f4a38SAtmn Patel   }
252ec8f4a38SAtmn Patel 
253ec8f4a38SAtmn Patel   printf("  %s\n", Line);
254ec8f4a38SAtmn Patel }
255ec8f4a38SAtmn Patel 
dump(__tgt_offload_entry * Entry)256ec8f4a38SAtmn Patel void dump(__tgt_offload_entry *Entry) {
257ec8f4a38SAtmn Patel   fprintf(stderr, "Entry (%p):\n", (void *)Entry);
258ec8f4a38SAtmn Patel   fprintf(stderr, "  Name: %s (%p)\n", Entry->name, (void *)&Entry->name);
259ec8f4a38SAtmn Patel   fprintf(stderr, "  Reserved: %d (%p)\n", Entry->reserved,
260ec8f4a38SAtmn Patel           (void *)&Entry->reserved);
261ec8f4a38SAtmn Patel   fprintf(stderr, "  Flags: %d (%p)\n", Entry->flags, (void *)&Entry->flags);
262ec8f4a38SAtmn Patel   fprintf(stderr, "  Addr: %p\n", Entry->addr);
263ec8f4a38SAtmn Patel   fprintf(stderr, "  Size: %lu\n", Entry->size);
264ec8f4a38SAtmn Patel }
265ec8f4a38SAtmn Patel 
dump(__tgt_target_table * Table)266ec8f4a38SAtmn Patel void dump(__tgt_target_table *Table) {
267ec8f4a38SAtmn Patel   for (auto *CurEntry = Table->EntriesBegin; CurEntry != Table->EntriesEnd;
268ec8f4a38SAtmn Patel        CurEntry++)
269ec8f4a38SAtmn Patel     dump(CurEntry);
270ec8f4a38SAtmn Patel }
271ec8f4a38SAtmn Patel 
dump(TargetOffloadEntry Entry)272ec8f4a38SAtmn Patel void dump(TargetOffloadEntry Entry) {
273ec8f4a38SAtmn Patel   fprintf(stderr, "Entry: ");
274*21e92612SAtmn Patel   fprintf(stderr, "  Name: %s\n", Entry.name().c_str());
275*21e92612SAtmn Patel   fprintf(stderr, "  Reserved: %d\n", Entry.reserved());
276*21e92612SAtmn Patel   fprintf(stderr, "  Flags: %d\n", Entry.flags());
277*21e92612SAtmn Patel   fprintf(stderr, "  Size:  %ld\n", Entry.data().size());
278ec8f4a38SAtmn Patel   dump(static_cast<const void *>(Entry.data().data()),
279ec8f4a38SAtmn Patel        static_cast<const void *>((Entry.data().c_str() + Entry.data().size())));
280ec8f4a38SAtmn Patel }
281ec8f4a38SAtmn Patel 
dump(__tgt_device_image * Image)282ec8f4a38SAtmn Patel void dump(__tgt_device_image *Image) {
283ec8f4a38SAtmn Patel   dump(Image->ImageStart, Image->ImageEnd);
284ec8f4a38SAtmn Patel   __tgt_offload_entry *EntryItr = Image->EntriesBegin;
285ec8f4a38SAtmn Patel   for (; EntryItr != Image->EntriesEnd; EntryItr++)
286ec8f4a38SAtmn Patel     dump(EntryItr);
287ec8f4a38SAtmn Patel }
288ec8f4a38SAtmn Patel 
dump(std::unordered_map<void *,__tgt_offload_entry * > & Map)289ec8f4a38SAtmn Patel void dump(std::unordered_map<void *, __tgt_offload_entry *> &Map) {
290ec8f4a38SAtmn Patel   fprintf(stderr, "Host to Remote Entry Map:\n");
291ec8f4a38SAtmn Patel   for (auto Entry : Map)
292ec8f4a38SAtmn Patel     fprintf(stderr, "  Host (%p) -> Tgt (%p): Addr((%p))\n", Entry.first,
293ec8f4a38SAtmn Patel             (void *)Entry.second, (void *)Entry.second->addr);
294ec8f4a38SAtmn Patel }
295ec8f4a38SAtmn Patel } // namespace RemoteOffloading
296