| //===-- 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); |
| } |
| } |
| } |
| ///} |