Files
TheRock/rocm-systems/projects/clr/rocclr/device/devprogram.hpp
T
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

420 lines
15 KiB
C++

/*
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include "platform/context.hpp"
#include "platform/object.hpp"
#include "platform/memory.hpp"
#include "amd_comgr/amd_comgr.h"
namespace amd {
namespace hsa {
namespace loader {
class Symbol;
} // namespace loader
namespace code {
namespace Kernel {
class Metadata;
} // namespace Kernel
} // namespace code
} // namespace hsa
} // namespace amd
namespace amd {
class Device;
class Program;
namespace option {
class Options;
} // namespace option
} // namespace amd
namespace amd::device {
class ClBinary;
class Kernel;
struct SymbolInfo {
int sym_type;
std::vector<std::string>* var_names;
};
struct SymbolLoweredName {
const char* name_expression;
std::string* loweredName;
};
//! A program object for a specific device.
class Program {
public:
typedef std::pair<const void* /* binary_image */, size_t /* binary size */> binary_t;
typedef std::pair<amd::Os::FileDesc /* file_desc */, size_t /* file_offset */> finfo_t;
typedef std::unordered_map<std::string_view, Kernel*> kernels_t;
// type of the program
typedef enum {
TYPE_NONE = 0, // uncompiled
TYPE_COMPILED, // compiled
TYPE_LIBRARY, // linked library
TYPE_EXECUTABLE, // linked executable
TYPE_INTERMEDIATE // intermediate
} type_t;
//! type of the input file
typedef enum {
FILE_TYPE_DEFAULT = 0,
FILE_TYPE_OPENCL = 1,
FILE_TYPE_LLVMIR_TEXT = 2,
FILE_TYPE_LLVMIR_BINARY = 3,
FILE_TYPE_SPIR_TEXT = 4,
FILE_TYPE_SPIR_BINARY = 5,
FILE_TYPE_AMDIL_TEXT = 6,
FILE_TYPE_AMDIL_BINARY = 7,
FILE_TYPE_X86_TEXT = 8,
FILE_TYPE_X86_BINARY = 9,
FILE_TYPE_CG = 10,
FILE_TYPE_SOURCE = 11,
FILE_TYPE_ISA = 12,
FILE_TYPE_HEADER = 13,
FILE_TYPE_RSLLVMIR_BINARY = 14,
FILE_TYPE_SPIRV_BINARY = 15,
FILE_TYPE_ASM_TEXT = 16,
FILE_TYPE_LAST = 17
} file_type_t;
private:
//! The device target for this binary.
amd::SharedReference<amd::Device> device_;
amd::Program& owner_; //!< owner of this program
kernels_t kernels_; //!< The kernel entry points this binary.
type_t type_; //!< type of this program
std::vector<const Kernel*> initKernels_; //!< Init kernels
std::vector<const Kernel*> finiKernels_; //!< Fini kernels
bool runInitFiniKernel(const std::vector<const Kernel*>& kernels) const;
protected:
union {
struct {
uint32_t isNull_ : 1; //!< Null program no memory allocations
uint32_t internal_ : 1; //!< Internal blit program
uint32_t hasGlobalStores_ : 1; //!< Program has writable program scope variables
uint32_t isHIP_ : 1; //!< Determine if the program is for HIP
uint32_t coLoaded_ : 1; //!< Has the code objected been loaded
uint32_t trapHandler_ : 1; //!< It is a trap handler for debugger
};
uint32_t flags_; //!< Program flags
};
ClBinary* clBinary_; //!< The CL program binary file
std::string llvmBinary_; //!< LLVM IR binary code
amd::Elf::ElfSections elfSectionType_; //!< LLVM IR binary code is in SPIR format
std::string compileOptions_; //!< compile/build options.
std::string linkOptions_; //!< link options.
//!< the option arg passed in to clCompileProgram(), clLinkProgram(),
//!< or clBuildProgram(), whichever is called last
std::string lastBuildOptionsArg_;
mutable std::string buildLog_; //!< build log.
int32_t buildStatus_; //!< build status.
int32_t buildError_; //!< build error
size_t globalVariableTotalSize_;
amd::option::Options* programOptions_;
amd_comgr_metadata_node_t metadata_ = {}; //!< COMgr metadata
uint32_t codeObjectVer_; //!< version of code object
std::map<std::string, amd_comgr_metadata_node_t> kernelMetadataMap_; //!< Map of kernel metadata
//! Sanitizer lock - lock when launching init/fini kernels
static std::recursive_mutex initFiniLock_;
public:
//! Construct a section.
Program(amd::Device& device, amd::Program& owner);
//! Destroy this binary image.
virtual ~Program();
//! Destroy all the kernels
void clear();
amd::Program* owner() const { return &owner_; }
//! Return the compiler options passed to build this program
amd::option::Options* getCompilerOptions() const { return programOptions_; }
//! Compile the device program.
int32_t compile(const std::string& sourceCode, const std::vector<const std::string*>& headers,
const char** headerIncludeNames, const char* origOptions,
amd::option::Options* options);
//! Link the device program.
int32_t link(const std::vector<Program*>& inputPrograms, const char* origLinkOptions,
amd::option::Options* linkOptions);
//! Build the device program.
int32_t build(const std::string& sourceCode, const char* origOptions,
amd::option::Options* options);
//! Load the device program.
bool load();
//! Return the device object, associated with this program.
const amd::Device& device() const { return device_(); }
//! Return the compiler options used to build the program.
const std::string& compileOptions() const { return compileOptions_; }
const std::string& linkOptions() const { return linkOptions_; }
//! Return the option arg passed in to clCompileProgram(), clLinkProgram(),
//! or clBuildProgram(), whichever is called last
const std::string lastBuildOptionsArg() const { return lastBuildOptionsArg_; }
//! Return the build log.
const std::string& buildLog() const { return buildLog_; }
//! Return the build status.
cl_build_status buildStatus() const { return buildStatus_; }
//! Return the build error.
int32_t buildError() const { return buildError_; }
//! Return the symbols vector.
const kernels_t& kernels() const { return kernels_; }
kernels_t& kernels() { return kernels_; }
//! Add kernel to the map and init fini kernel vector.
void addKernel(Kernel* k);
//! Return the binary image.
inline const binary_t binary() const;
inline binary_t binary();
inline finfo_t BinaryFd() const;
inline std::string BinaryURI() const;
//! Returns the CL program binary file
ClBinary* clBinary() { return clBinary_; }
const ClBinary* clBinary() const { return clBinary_; }
bool setBinary(const char* binaryIn, size_t size, const device::Program* same_dev_prog = nullptr,
amd::Os::FileDesc fdesc = amd::Os::FDescInit(), size_t foffset = 0,
std::string uri = std::string());
type_t type() const { return type_; }
void setGlobalVariableTotalSize(size_t size) { globalVariableTotalSize_ = size; }
size_t globalVariableTotalSize() const { return globalVariableTotalSize_; }
//! Returns TRUE if the program just compiled
bool isNull() const { return isNull_; }
//! Returns TRUE if the program used internally by runtime
bool isInternal() const { return internal_; }
//! Global variables are a part of the code segment
bool hasGlobalStores() const { return hasGlobalStores_; }
//! Return TRUE if the program has been loaded
bool isCodeObjectLoaded() const { return coLoaded_; }
//! Returns TRUE if the program is a trap handler for debugger support
bool isTrapHandler() const { return trapHandler_; }
amd_comgr_metadata_node_t metadata() const { return metadata_; }
//! Get the kernel metadata
const bool getKernelMetadata(const std::string& name, amd_comgr_metadata_node_t* meta) const {
auto it = kernelMetadataMap_.find(name);
if (it != kernelMetadataMap_.end()) {
*meta = it->second;
return true;
}
return false;
}
const uint32_t codeObjectVer() const { return codeObjectVer_; }
//! Check if program is HIP based
const bool isHIP() const { return (isHIP_ == 1); }
//! Get mangled name of a name expresion
const bool getLoweredNames(std::vector<std::string>* mangledNames) const;
//! Get demangled names
bool getDemangledName(const std::string& mangledNames, std::string& demangledNames) const;
bool getGlobalFuncFromCodeObj(std::vector<std::string>* func_names) const;
bool getGlobalVarFromCodeObj(std::vector<std::string>* var_names) const;
bool getUndefinedVarFromCodeObj(std::vector<std::string>* var_names) const;
virtual bool createGlobalVarObj(amd::Memory** amd_mem_obj, void** dptr, size_t* bytes,
const char* globalName) const {
ShouldNotReachHere();
return false;
}
//! Run kernels marked with "init" kind metadata
bool runInitKernels();
//! Run kernels marked with "fini" kind metadata
bool runFiniKernels();
protected:
//! pre-compile setup
bool initBuild(amd::option::Options* options);
//! post-compile cleanup
bool finiBuild(bool isBuildGood);
/*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
*
* \return True if we successefully compiled a GPU program
*/
bool compileImpl(const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
);
//! Link the device program.
bool linkImpl(amd::option::Options* options);
//! Link the device programs.
bool linkImpl(const std::vector<Program*>& inputPrograms, amd::option::Options* options,
bool createLibrary);
virtual bool createBinary(amd::option::Options* options) = 0;
//! Initialize Binary (used only for clCreateProgramWithBinary()).
bool initClBinary(const char* binaryIn, size_t size,
amd::Os::FileDesc fdesc = amd::Os::FDescInit(), size_t foffset = 0,
std::string uri = std::string());
//! Initialize Binary
virtual bool initClBinary();
//! Release the Binary
void releaseClBinary();
virtual bool createKernels(void* binary, size_t binSize, bool useUniformWorkGroupSize,
bool internalKernel) {
return true;
}
virtual bool setKernels(void* binary, size_t binSize,
amd::Os::FileDesc fdesc = amd::Os::FDescInit(), size_t foffset = 0,
std::string uri = std::string()) {
return true;
}
//! Returns all the options to be appended while passing to the compiler library
std::vector<std::string> ProcessOptions(amd::option::Options* options);
//! Returns all the options to be appended while passing to the compiler library,
//! flattened into one string.
std::string ProcessOptionsFlattened(amd::option::Options* options);
//! At linking time, get the set of compile options to be used from
//! the set of input program, warn if they have inconsisten compile options.
bool getCompileOptionsAtLinking(const std::vector<Program*>& inputPrograms,
const amd::option::Options* linkOptions);
void setType(type_t newType) { type_ = newType; }
/* \brief Returns the next stage to compile from, based on sections in binary,
* also returns completeStages in a vector, which contains at least ACL_TYPE_DEFAULT,
* sets needOptionsCheck to true if options check is needed to decide whether or not to recompile
*/
file_type_t getCompilationStagesFromBinary(std::vector<file_type_t>& completeStages,
bool& needOptionsCheck);
/* \brief Returns the next stage to compile from, based on sections and options in binary
*/
file_type_t getNextCompilationStageFromBinary(amd::option::Options* options);
//! Finds the total size of all global variables in the program
bool FindGlobalVarSize(void* binary, size_t binSize);
bool isElf(const char* bin) const { return amd::Elf::isElfMagic(bin); }
virtual bool defineGlobalVar(const char* name, void* dptr) {
ShouldNotReachHere();
return false;
}
bool getSymbolsFromCodeObj(std::vector<std::string>* var_names,
amd_comgr_symbol_type_t sym_type) const;
bool getUndefinedVarInfo(std::string var_name, void** var_addr, size_t* var_size);
bool defineUndefinedVars();
private:
//! Dump the log data object to the build log, if a log data object is present
void extractBuildLog(amd_comgr_data_set_t dataSet);
//! Dump the code object data
amd_comgr_status_t extractByteCodeBinary(const amd_comgr_data_set_t inDataSet,
const amd_comgr_data_kind_t dataKind,
const std::string& outFileName,
char* outBinary[] = nullptr, size_t* outSize = nullptr);
//! Create code object and add it into the data set
amd_comgr_status_t addCodeObjData(const char* source, const size_t size,
const amd_comgr_data_kind_t type, const char* name,
amd_comgr_data_set_t* dataSet);
//! Create action for the specified language, target and options
amd_comgr_status_t createAction(const amd_comgr_language_t oclver,
const std::vector<std::string>& options,
amd_comgr_action_info_t* action, bool* hasAction);
//! Create the bitcode of the linked input dataset
bool linkLLVMBitcode(const amd_comgr_data_set_t inputs, const std::vector<std::string>& options,
amd::option::Options* amdOptions, amd_comgr_data_set_t* output,
char* binaryData[] = nullptr, size_t* binarySize = nullptr);
//! Create the bitcode of the compiled input dataset
bool compileToLLVMBitcode(const amd_comgr_data_set_t compileInputs,
const std::vector<std::string>& options,
amd::option::Options* amdOptions, char* binaryData[],
size_t* binarySize, const bool link_dev_libs = true);
//! Compile and create the excutable of the input dataset
bool compileAndLinkExecutable(const amd_comgr_data_set_t inputs,
const std::vector<std::string>& options,
amd::option::Options* amdOptions, char* executable[],
size_t* executableSize, file_type_t continueCompileFrom);
//! Create the map for the kernel name and its metadata for fast access
bool createKernelMetadataMap(void* binary, size_t binSize);
bool trySubstObjFile(const char* SubstCfgFile, const std::string& sourceCode,
const amd::option::Options* options);
//! Disable default copy constructor
Program(const Program&);
//! Disable operator=
Program& operator=(const Program&);
};
class ComgrBinaryData {
public:
ComgrBinaryData() : binaryData_({0}), created_(false) {}
~ComgrBinaryData();
bool create(amd_comgr_data_kind_t kind, void* binary, size_t binSize);
amd_comgr_data_t& data();
private:
amd_comgr_data_t binaryData_;
bool created_;
};
} // namespace amd::device