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