Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

301 lines
8.7 KiB
C++

/*
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#include "rocprogram.hpp"
#include "utils/options.hpp"
#include "rockernel.hpp"
#include "rocurilocator.hpp"
#include <string>
#include <vector>
#include <cstring>
#include <fstream>
#include <sstream>
#include <iostream>
#include <iterator>
namespace amd::roc {
static inline const char* hsa_strerror(hsa_status_t status) {
const char* str = nullptr;
if (Hsa::status_string(status, &str) == HSA_STATUS_SUCCESS) {
return str;
}
return "Unknown error";
}
Program::~Program() {
// Destroy the executable.
if (hsaExecutable_.handle != 0) {
Hsa::executable_destroy(hsaExecutable_);
}
if (hsaCodeObjectReader_.handle != 0) {
Hsa::code_object_reader_destroy(hsaCodeObjectReader_);
}
releaseClBinary();
}
Program::Program(roc::NullDevice& device, amd::Program& owner) : device::Program(device, owner) {
hsaExecutable_.handle = 0;
hsaCodeObjectReader_.handle = 0;
isHIP_ = (owner.language() == amd::Program::HIP);
}
bool Program::initClBinary(char* binaryIn, size_t size) {
// Save the original binary that isn't owned by ClBinary
clBinary()->saveOrigBinary(binaryIn, size);
char* bin = binaryIn;
size_t sz = size;
int encryptCode;
char* decryptedBin;
size_t decryptedSize;
if (!clBinary()->decryptElf(binaryIn, size, &decryptedBin, &decryptedSize, &encryptCode)) {
buildLog_ += "Decrypting ELF Failed\n";
return false;
}
if (decryptedBin != nullptr) {
// It is decrypted binary.
bin = decryptedBin;
sz = decryptedSize;
}
// Both 32-bit and 64-bit are allowed!
if (!amd::Elf::isElfMagic(bin)) {
// Invalid binary.
delete[] decryptedBin;
buildLog_ += "Elf Magic failed\n";
return false;
}
clBinary()->setFlags(encryptCode);
return clBinary()->setBinary(bin, sz, (decryptedBin != nullptr));
}
bool Program::defineGlobalVar(const char* name, void* dptr) {
if (!device().isOnline()) {
return false;
}
hsa_agent_t hsa_device = rocDevice().getBackendDevice();
hsa_status_t status =
Hsa::executable_agent_global_variable_define(hsaExecutable_, hsa_device, name, dptr);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Could not define global variable : ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
}
return (status == HSA_STATUS_SUCCESS);
}
bool Program::createGlobalVarObj(amd::Memory** amd_mem_obj, void** device_pptr, size_t* bytes,
const char* global_name) const {
if (!device().isOnline()) {
return false;
}
hsa_status_t status = HSA_STATUS_SUCCESS;
const roc::Device* roc_device = nullptr;
hsa_agent_t hsa_device;
hsa_symbol_kind_t sym_type;
hsa_executable_symbol_t global_symbol;
if (amd_mem_obj == nullptr) {
buildLog_ += "amd_mem_obj is null";
buildLog_ += "\n";
return false;
}
hsa_device = rocDevice().getBackendDevice();
/* Find HSA Symbol by name */
status =
Hsa::executable_get_symbol_by_name(hsaExecutable_, global_name, &hsa_device, &global_symbol);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Failed to find the Symbol by Name: ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
/* Find HSA Symbol Type */
status =
Hsa::executable_symbol_get_info(global_symbol, HSA_EXECUTABLE_SYMBOL_INFO_TYPE, &sym_type);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Failed to find the Symbol Type : ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
/* Make sure symbol type is VARIABLE */
if (sym_type != HSA_SYMBOL_KIND_VARIABLE) {
buildLog_ += "Error: Symbol is not of type VARIABLE : ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
/* Retrieve the size of the variable */
status = Hsa::executable_symbol_get_info(global_symbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_SIZE,
bytes);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Failed to retrieve the Symbol Size : ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
// Handle size 0 symbols
if (*bytes != 0) {
// Find HSA Symbol Address
status = Hsa::executable_symbol_get_info(
global_symbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_ADDRESS, device_pptr);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Failed to find the Symbol Address : ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
roc_device = &(rocDevice());
*amd_mem_obj = new (roc_device->context())
amd::Buffer(roc_device->context(), ROCCLR_MEM_INTERNAL_MEMORY, *bytes, *device_pptr);
if (*amd_mem_obj == nullptr) {
buildLog_ += "[OCL] Failed to create a mem object!";
buildLog_ += "\n";
return false;
}
if (!((*amd_mem_obj)->create(nullptr))) {
buildLog_ += "[OCL] failed to create a svm hidden buffer!";
buildLog_ += "\n";
(*amd_mem_obj)->release();
return false;
}
}
return true;
}
bool Program::createBinary(amd::option::Options* options) {
if (!clBinary()->createElfBinary(options->oVariables->BinEncrypt, type())) {
LogError("Failed to create ELF binary image!");
return false;
}
return true;
}
bool Program::createKernels(void* binary, size_t binSize, bool useUniformWorkGroupSize,
bool internalKernel) {
// Find the size of global variables from the binary
if (!FindGlobalVarSize(binary, binSize)) {
buildLog_ += "Error: Cannot Find Global Var Sizes\n";
return false;
}
for (const auto& kernelMeta : kernelMetadataMap_) {
const std::string kernelName = kernelMeta.first;
Kernel* aKernel = new roc::Kernel(kernelName, this);
if (!aKernel->init()) {
return false;
}
if (codeObjectVer() < 5) {
aKernel->setUniformWorkGroupSize(useUniformWorkGroupSize);
}
aKernel->setInternalKernelFlag(internalKernel);
addKernel(aKernel);
}
return true;
}
bool Program::setKernels(void* binary, size_t binSize, amd::Os::FileDesc fdesc,
size_t foffset, std::string uri) {
// Stop compilation if it is an offline device - HSA runtime does not
// support ISA compiled offline
if (!device().isOnline()) {
return true;
}
hsa_agent_t agent = rocDevice().getBackendDevice();
hsa_status_t status;
status = Hsa::executable_create_alt(HSA_PROFILE_FULL, HSA_DEFAULT_FLOAT_ROUNDING_MODE_DEFAULT,
nullptr, &hsaExecutable_);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Executable for AMD HSA Code Object isn't created: ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
// If we received a file descriptor, hand the code object's file region to
// rocr via the vendor extension so it can mmap it itself (and resolve the
// URI directly from the fd). Fall back to from_memory when the fd is
// invalid or the vendor extension isn't available in the linked rocr.
// The fd is owned by setKernels in all cases: closed before returning.
auto* create_from_file =
Device::loaderExtensionTable()
.hsa_ven_amd_loader_code_object_reader_create_from_file_with_offset_size;
if (fdesc != amd::Os::FDescInit() && create_from_file != nullptr) {
status = create_from_file(fdesc, foffset, binSize, &hsaCodeObjectReader_);
} else {
status = Hsa::code_object_reader_create_from_memory(binary, binSize, &hsaCodeObjectReader_);
}
if (fdesc != amd::Os::FDescInit()) {
amd::Os::CloseFileHandle(fdesc);
}
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: AMD HSA Code Object Reader create failed: ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
status = Hsa::executable_load_agent_code_object(hsaExecutable_, agent, hsaCodeObjectReader_,
nullptr, nullptr);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: AMD HSA Code Object loading failed: ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
// Freeze the executable.
status = Hsa::executable_freeze(hsaExecutable_, nullptr);
if (status != HSA_STATUS_SUCCESS) {
buildLog_ += "Error: Freezing the executable failed: ";
buildLog_ += hsa_strerror(status);
buildLog_ += "\n";
return false;
}
#if defined(__linux__) && defined(__clang__)
#if __has_feature(address_sanitizer)
UriLocator::recordCodeObjects(hsaExecutable_);
#endif
#endif
for (auto& kit : kernels()) {
Kernel* kernel = static_cast<Kernel*>(kit.second);
if (!kernel->postLoad()) {
return false;
}
}
return true;
}
} // namespace amd::roc