blob: 03d868b8fd5eef4581349af3ebc6b8c774abd2d9 [file] [log] [blame]
//===---------------- Utils.cpp - Utilities for Remote RTL ----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Utilities for data movement and debugging.
//
//===----------------------------------------------------------------------===//
#include "Utils.h"
#include "omptarget.h"
namespace RemoteOffloading {
void loadTargetBinaryDescription(const __tgt_bin_desc *Desc,
TargetBinaryDescription &Request) {
// Keeps track of entries which have already been deep copied.
std::vector<void *> DeepCopiedEntryAddrs;
// Copy Global Offload Entries
for (auto *CurEntry = Desc->HostEntriesBegin;
CurEntry != Desc->HostEntriesEnd; CurEntry++) {
auto *NewEntry = Request.add_entries();
copyOffloadEntry(CurEntry, NewEntry);
// Copy the pointer of the offload entry of the image into the Request
Request.add_entry_ptrs((uint64_t)CurEntry);
DeepCopiedEntryAddrs.push_back(CurEntry);
}
// Copy Device Images and Device Offload Entries
__tgt_device_image *CurImage = Desc->DeviceImages;
for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++) {
auto *Image = Request.add_images();
auto Size = (char *)CurImage->ImageEnd - (char *)CurImage->ImageStart;
Image->set_binary(CurImage->ImageStart, Size);
// Copy the pointer of the image into the Request
auto *NewImagePtr = Request.add_image_ptrs();
NewImagePtr->set_img_ptr((uint64_t)CurImage->ImageStart);
// Copy Device Offload Entries
for (auto *CurEntry = CurImage->EntriesBegin;
CurEntry != CurImage->EntriesEnd; CurEntry++) {
auto *NewEntry = Image->add_entries();
auto Entry = std::find(DeepCopiedEntryAddrs.begin(),
DeepCopiedEntryAddrs.end(), CurEntry);
if (Entry != DeepCopiedEntryAddrs.end()) {
// Offload entry has already been loaded
shallowCopyOffloadEntry(CurEntry, NewEntry);
} else { // Offload Entry has not been loaded into the Request
copyOffloadEntry(CurEntry, NewEntry);
DeepCopiedEntryAddrs.push_back(CurEntry);
}
// Copy the pointer of the offload entry of the image into the Request
NewImagePtr->add_entry_ptrs((uint64_t)CurEntry);
}
}
}
void unloadTargetBinaryDescription(
const TargetBinaryDescription *Request, __tgt_bin_desc *Desc,
std::unordered_map<const void *, __tgt_device_image *>
&HostToRemoteDeviceImage) {
std::unordered_map<const void *, __tgt_offload_entry *> CopiedOffloadEntries;
Desc->NumDeviceImages = Request->images_size();
Desc->DeviceImages = new __tgt_device_image[Desc->NumDeviceImages];
if (Request->entries_size())
Desc->HostEntriesBegin = new __tgt_offload_entry[Request->entries_size()];
else {
Desc->HostEntriesBegin = nullptr;
Desc->HostEntriesEnd = nullptr;
}
// Copy Global Offload Entries
__tgt_offload_entry *CurEntry = Desc->HostEntriesBegin;
size_t I = 0;
for (auto &Entry : Request->entries()) {
copyOffloadEntry(Entry, CurEntry);
CopiedOffloadEntries[(void *)Request->entry_ptrs()[I]] = CurEntry;
CurEntry++;
I++;
}
Desc->HostEntriesEnd = CurEntry;
// Copy Device Images and Device Offload Entries
__tgt_device_image *CurImage = Desc->DeviceImages;
auto ImageItr = Request->image_ptrs().begin();
for (auto Image : Request->images()) {
// Copy Device Offload Entries
CurEntry = Desc->HostEntriesBegin;
bool Found = false;
if (!Desc->HostEntriesBegin) {
CurImage->EntriesBegin = nullptr;
CurImage->EntriesEnd = nullptr;
}
for (size_t I = 0; I < Image.entries_size(); I++) {
auto TgtEntry =
CopiedOffloadEntries.find((void *)Request->entry_ptrs()[I]);
if (TgtEntry != CopiedOffloadEntries.end()) {
if (!Found)
CurImage->EntriesBegin = CurEntry;
CurImage->EntriesEnd = CurEntry + 1;
Found = true;
} else {
Found = false;
copyOffloadEntry(Image.entries()[I], CurEntry);
CopiedOffloadEntries[(void *)(Request->entry_ptrs()[I])] = CurEntry;
}
CurEntry++;
}
// Copy Device Image
CurImage->ImageStart = new uint8_t[Image.binary().size()];
memcpy(CurImage->ImageStart,
static_cast<const void *>(Image.binary().data()),
Image.binary().size());
CurImage->ImageEnd =
(void *)((char *)CurImage->ImageStart + Image.binary().size());
HostToRemoteDeviceImage[(void *)ImageItr->img_ptr()] = CurImage;
CurImage++;
ImageItr++;
}
}
void freeTargetBinaryDescription(__tgt_bin_desc *Desc) {
__tgt_device_image *CurImage = Desc->DeviceImages;
for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++)
delete[](uint64_t *) CurImage->ImageStart;
delete[] Desc->DeviceImages;
for (auto *Entry = Desc->HostEntriesBegin; Entry != Desc->HostEntriesEnd;
Entry++) {
free(Entry->name);
free(Entry->addr);
}
delete[] Desc->HostEntriesBegin;
}
void freeTargetTable(__tgt_target_table *Table) {
for (auto *Entry = Table->EntriesBegin; Entry != Table->EntriesEnd; Entry++)
free(Entry->name);
delete[] Table->EntriesBegin;
}
void loadTargetTable(__tgt_target_table *Table, TargetTable &TableResponse,
__tgt_device_image *Image) {
auto *ImageEntry = Image->EntriesBegin;
for (__tgt_offload_entry *CurEntry = Table->EntriesBegin;
CurEntry != Table->EntriesEnd; CurEntry++, ImageEntry++) {
// TODO: This can probably be trimmed substantially.
auto *NewEntry = TableResponse.add_entries();
NewEntry->set_name(CurEntry->name);
NewEntry->set_addr((uint64_t)CurEntry->addr);
NewEntry->set_flags(CurEntry->flags);
NewEntry->set_reserved(CurEntry->reserved);
NewEntry->set_size(CurEntry->size);
TableResponse.add_entry_ptrs((int64_t)CurEntry);
}
}
void unloadTargetTable(
TargetTable &TableResponse, __tgt_target_table *Table,
std::unordered_map<void *, void *> &HostToRemoteTargetTableMap) {
Table->EntriesBegin = new __tgt_offload_entry[TableResponse.entries_size()];
auto *CurEntry = Table->EntriesBegin;
for (size_t I = 0; I < TableResponse.entries_size(); I++) {
copyOffloadEntry(TableResponse.entries()[I], CurEntry);
HostToRemoteTargetTableMap[CurEntry->addr] =
(void *)TableResponse.entry_ptrs()[I];
CurEntry++;
}
Table->EntriesEnd = CurEntry;
}
void copyOffloadEntry(const TargetOffloadEntry &EntryResponse,
__tgt_offload_entry *Entry) {
Entry->name = strdup(EntryResponse.name().c_str());
Entry->reserved = EntryResponse.reserved();
Entry->flags = EntryResponse.flags();
Entry->addr = strdup(EntryResponse.data().c_str());
Entry->size = EntryResponse.data().size();
}
void copyOffloadEntry(const DeviceOffloadEntry &EntryResponse,
__tgt_offload_entry *Entry) {
Entry->name = strdup(EntryResponse.name().c_str());
Entry->reserved = EntryResponse.reserved();
Entry->flags = EntryResponse.flags();
Entry->addr = (void *)EntryResponse.addr();
Entry->size = EntryResponse.size();
}
/// We shallow copy with just the name because it is a convenient identifier, we
/// do actually just match off of the address.
void shallowCopyOffloadEntry(const __tgt_offload_entry *Entry,
TargetOffloadEntry *EntryResponse) {
EntryResponse->set_name(Entry->name);
}
void copyOffloadEntry(const __tgt_offload_entry *Entry,
TargetOffloadEntry *EntryResponse) {
shallowCopyOffloadEntry(Entry, EntryResponse);
EntryResponse->set_reserved(Entry->reserved);
EntryResponse->set_flags(Entry->flags);
EntryResponse->set_data(Entry->addr, Entry->size);
}
/// Dumps the memory region from Start to End in order to debug memory transfer
/// errors within the plugin
void dump(const void *Start, const void *End) {
unsigned char Line[17];
const unsigned char *PrintCharacter = (const unsigned char *)Start;
unsigned int I = 0;
for (; I < ((const int *)End - (const int *)Start); I++) {
if ((I % 16) == 0) {
if (I != 0)
printf(" %s\n", Line);
printf(" %04x ", I);
}
printf(" %02x", PrintCharacter[I]);
if ((PrintCharacter[I] < 0x20) || (PrintCharacter[I] > 0x7e))
Line[I % 16] = '.';
else
Line[I % 16] = PrintCharacter[I];
Line[(I % 16) + 1] = '\0';
}
while ((I % 16) != 0) {
printf(" ");
I++;
}
printf(" %s\n", Line);
}
void dump(__tgt_offload_entry *Entry) {
fprintf(stderr, "Entry (%p):\n", (void *)Entry);
fprintf(stderr, " Name: %s (%p)\n", Entry->name, (void *)&Entry->name);
fprintf(stderr, " Reserved: %d (%p)\n", Entry->reserved,
(void *)&Entry->reserved);
fprintf(stderr, " Flags: %d (%p)\n", Entry->flags, (void *)&Entry->flags);
fprintf(stderr, " Addr: %p\n", Entry->addr);
fprintf(stderr, " Size: %lu\n", Entry->size);
}
void dump(__tgt_target_table *Table) {
for (auto *CurEntry = Table->EntriesBegin; CurEntry != Table->EntriesEnd;
CurEntry++)
dump(CurEntry);
}
void dump(TargetOffloadEntry Entry) {
fprintf(stderr, "Entry: ");
fprintf(stderr, " Name: %s\n", Entry.name().c_str());
fprintf(stderr, " Reserved: %d\n", Entry.reserved());
fprintf(stderr, " Flags: %d\n", Entry.flags());
fprintf(stderr, " Size: %ld\n", Entry.data().size());
dump(static_cast<const void *>(Entry.data().data()),
static_cast<const void *>((Entry.data().c_str() + Entry.data().size())));
}
void dump(__tgt_device_image *Image) {
dump(Image->ImageStart, Image->ImageEnd);
__tgt_offload_entry *EntryItr = Image->EntriesBegin;
for (; EntryItr != Image->EntriesEnd; EntryItr++)
dump(EntryItr);
}
void dump(std::unordered_map<void *, __tgt_offload_entry *> &Map) {
fprintf(stderr, "Host to Remote Entry Map:\n");
for (auto Entry : Map)
fprintf(stderr, " Host (%p) -> Tgt (%p): Addr((%p))\n", Entry.first,
(void *)Entry.second, (void *)Entry.second->addr);
}
} // namespace RemoteOffloading