blob: 47decd3f369d4db8dbc1cce42fc0217591201373 [file] [edit]
//===-- LanguageRegistration.cpp - Language registration API --------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "LanguageRegistration.h"
#include "OffloadAPI.h"
#include "State.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/Offloading/Utility.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <cstring>
#include <inttypes.h>
using RuntimeState = llvm::offload::StateTy;
using ThreadState = llvm::offload::ThreadStateTy;
/// Hidden, but exported, Registration API
///{
extern "C" {
void __llvmRegisterFunction(const char *Binary, const char *KernelID,
char *KernelName, const char *KernelName1, int,
uint3 *, uint3 *, dim3 *, dim3 *, int *) {
RuntimeState &State = RuntimeState::get();
ol_symbol_handle_t Kernel;
ol_program_handle_t Program = State.getProgram(Binary);
ol_result_t Result = olGetSymbol(
Program, KernelName, ol_symbol_kind_t::OL_SYMBOL_KIND_KERNEL, &Kernel);
CHECK_FATAL(Result, "Failed to get kernel symbol for " << KernelName);
State.registerKernel(KernelID, Kernel);
}
void __llvmRegisterVar(void **, char *, char *, const char *, int, int, int,
int) {
llvm::errs() << "RegisterVar is not implemented!" << "\n";
}
void __llvmRegisterManagedVar(void **, char *, char *, const char *, size_t,
unsigned) {
llvm::errs() << "RegisterManagedVar is not implemented!" << "\n";
}
void __llvmRegisterSurface(void **, const struct surfaceReference *,
const void **, const char *, int, int) {
llvm::errs() << "RegisterSurface is not implemented!" << "\n";
}
void __llvmRegisterTexture(void **, const struct textureReference *,
const void **, const char *, int, int, int) {
llvm::errs() << "RegisterTexture is not implemented!" << "\n";
}
/// This struct is a record of the device image information
struct __tgt_device_image {
void *ImageStart; // Pointer to the target code start
void *ImageEnd; // Pointer to the target code end
llvm::offloading::EntryTy
*EntriesBegin; // Begin of table with all target entries
llvm::offloading::EntryTy *EntriesEnd; // End of table (non inclusive)
};
/// This struct is a record of all the host code that may be offloaded to a
/// target.
struct __tgt_bin_desc {
int32_t NumDeviceImages; // Number of device types supported
__tgt_device_image *DeviceImages; // Array of device images (1 per dev. type)
llvm::offloading::EntryTy
*HostEntriesBegin; // Begin of table with all host entries
llvm::offloading::EntryTy *HostEntriesEnd; // End of table (non inclusive)
};
void __tgt_register_lib(__tgt_bin_desc *Desc) {
// TODO: For each device, lazily.
RuntimeState &State = RuntimeState::get();
ThreadState &Thread = ThreadState::get();
ol_device_handle_t Device = Thread.getDefaultDevice();
ol_context_handle_t Context = State.getContext();
for (int32_t I = 0, E = Desc->NumDeviceImages; I < E; ++I) {
ol_program_handle_t Program = nullptr;
__tgt_device_image &DeviceImage = Desc->DeviceImages[I];
void *ProgramData = DeviceImage.ImageStart;
size_t ProgramSize =
(char *)DeviceImage.ImageEnd - (char *)DeviceImage.ImageStart;
ol_result_t Result =
olCreateProgram(Context, Device, ProgramData, ProgramSize, &Program);
if (Result && Result->Code) {
fprintf(stderr, "Failed to register device code (%i): %s\n", Result->Code,
Result->Details);
abort();
}
State.registerProgram(DeviceImage.ImageStart, Program);
for (auto *Entry = DeviceImage.EntriesBegin;
Entry != DeviceImage.EntriesEnd; ++Entry) {
if (!Entry->Size && !Entry->Flags)
__llvmRegisterFunction((const char *)DeviceImage.ImageStart,
(const char *)Entry->Address, Entry->SymbolName,
Entry->SymbolName, 0, nullptr, nullptr, nullptr,
nullptr, nullptr);
}
}
}
void __tgt_unregister_lib(__tgt_bin_desc *Desc) {
RuntimeState *State = RuntimeState::tryGet();
if (!State)
return;
for (int32_t I = 0, E = Desc->NumDeviceImages; I < E; ++I) {
__tgt_device_image &DeviceImage = Desc->DeviceImages[I];
for (auto *Entry = DeviceImage.EntriesBegin;
Entry != DeviceImage.EntriesEnd; ++Entry) {
if (!Entry->Size && !Entry->Flags)
State->unregisterKernel((const char *)Entry->Address);
}
if (ol_program_handle_t Program =
State->unregisterProgram(DeviceImage.ImageStart))
olDestroyProgram(Program);
}
}
}
///}