From a66c56d641902abe96a638e95652a92e26460540 Mon Sep 17 00:00:00 2001 From: kjayapra-amd Date: Mon, 3 Aug 2020 11:21:37 -0400 Subject: [PATCH] SWDEV-241902 - Changes to pass file descriptor and offset to load code object. Change-Id: I0243cccdeaa533b2a56fde42f12d5424c3b63a3b --- rocclr/device/device.cpp | 14 ++++++- rocclr/device/device.hpp | 28 +++++++++++-- rocclr/device/devprogram.cpp | 19 ++++++--- rocclr/device/devprogram.hpp | 15 +++++-- rocclr/device/pal/palprogram.cpp | 6 ++- rocclr/device/pal/palprogram.hpp | 4 +- rocclr/device/rocm/rocprogram.cpp | 10 +++-- rocclr/device/rocm/rocprogram.hpp | 8 +++- rocclr/os/os.cpp | 0 rocclr/os/os.hpp | 21 ++++++++++ rocclr/os/os_posix.cpp | 65 ++++++++++++++++++++++++++++++- rocclr/os/os_win32.cpp | 44 +++++++++++++++++++++ rocclr/platform/program.cpp | 17 ++++---- rocclr/platform/program.hpp | 14 +++---- 14 files changed, 220 insertions(+), 45 deletions(-) mode change 100644 => 100755 rocclr/device/pal/palprogram.cpp mode change 100644 => 100755 rocclr/device/pal/palprogram.hpp mode change 100644 => 100755 rocclr/device/rocm/rocprogram.cpp mode change 100644 => 100755 rocclr/device/rocm/rocprogram.hpp mode change 100644 => 100755 rocclr/os/os.cpp mode change 100644 => 100755 rocclr/os/os.hpp mode change 100644 => 100755 rocclr/os/os_win32.cpp diff --git a/rocclr/device/device.cpp b/rocclr/device/device.cpp index 1aa326df9d..d926563d26 100755 --- a/rocclr/device/device.cpp +++ b/rocclr/device/device.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-present Advanced Micro Devices, Inc. +/* Copyright (c) 2008-presenet Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -759,7 +759,12 @@ bool ClBinary::createElfBinary(bool doencrypt, Program::type_t type) { Program::binary_t ClBinary::data() const { return {binary_, size_}; } -bool ClBinary::setBinary(const char* theBinary, size_t theBinarySize, bool allocated) { +Program::finfo_t ClBinary::Datafd() const { return {fdesc_, foffset_}; } + +std::string ClBinary::DataURI() const { return uri_; } + +bool ClBinary::setBinary(const char* theBinary, size_t theBinarySize, bool allocated, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { release(); size_ = theBinarySize; @@ -767,6 +772,11 @@ bool ClBinary::setBinary(const char* theBinary, size_t theBinarySize, bool alloc if (allocated) { flags_ |= BinaryAllocated; } + + fdesc_ = fdesc; + foffset_ = foffset; + uri_ = uri; + return true; } diff --git a/rocclr/device/device.hpp b/rocclr/device/device.hpp index 6ea126a9e3..e9129b0b76 100755 --- a/rocclr/device/device.hpp +++ b/rocclr/device/device.hpp @@ -869,9 +869,9 @@ class ClBinary : public amd::HeapObject { void init(amd::option::Options* optionsObj, bool amdilRequired = false); - /** called only in loading image routines, - never called in storing routines */ - bool setBinary(const char* theBinary, size_t theBinarySize, bool allocated = false); + /** called only in loading image routines, never storing routines */ + bool setBinary(const char* theBinary, size_t theBinarySize, bool allocated = false, + amd::Os::FileDesc fd = -1, size_t foffset = 0, std::string uri = std::string()); //! setin elfIn_ bool setElfIn(); @@ -900,8 +900,10 @@ class ClBinary : public amd::HeapObject { bool decryptElf(const char* binaryIn, size_t size, char** decryptBin, size_t* decryptSize, int* encryptCode); - //! Returns the binary pair for the abstraction layer + //! Returns the binary pair, fdesc pair, uri for the abstraction layer Program::binary_t data() const; + Program::finfo_t Datafd() const; + std::string DataURI() const; //! Loads llvmir binary from OCL binary file bool loadLlvmBinary( @@ -1016,6 +1018,10 @@ class ClBinary : public amd::HeapObject { size_t size_; //!< binary size uint flags_; //!< CL binary object flags + amd::Os::FileDesc fdesc_; //!< file descriptor + size_t foffset_; //!< file offset + std::string uri_; //!< memory URI + const char* origBinary_; //!< original binary data size_t origSize_; //!< original binary size @@ -1034,6 +1040,20 @@ inline const Program::binary_t Program::binary() const { return clBinary()->data(); } +inline std::string Program::BinaryURI() const { + if (clBinary() == NULL) { + return std::string(); + } + return clBinary()->DataURI(); +} + +inline Program::finfo_t Program::BinaryFd() const { + if (clBinary() == NULL) { + return {-1, 0}; + } + return clBinary()->Datafd(); +} + inline Program::binary_t Program::binary() { if (clBinary() == NULL) { return {(const void*)0, 0}; diff --git a/rocclr/device/devprogram.cpp b/rocclr/device/devprogram.cpp index eeaa4be5c3..9376adcf2f 100755 --- a/rocclr/device/devprogram.cpp +++ b/rocclr/device/devprogram.cpp @@ -1089,10 +1089,12 @@ bool Program::linkImplLC(amd::option::Options* options) { case ACL_TYPE_ISA: { amd::Comgr::destroy_data_set(inputs); binary_t isaBinary = binary(); + finfo_t isaFdesc = BinaryFd(); if (GPU_DUMP_CODE_OBJECT) { dumpCodeObject(std::string{(const char*)isaBinary.first, isaBinary.second}); } - return setKernels(options, const_cast(isaBinary.first), isaBinary.second); + return setKernels(options, const_cast(isaBinary.first), isaBinary.second, + isaFdesc.first, isaFdesc.second, BinaryURI()); break; } default: @@ -1852,7 +1854,8 @@ bool isSPIRVMagicL(const void* Image, size_t Length) { } // ================================================================================================ -bool Program::initClBinary(const char* binaryIn, size_t size) { +bool Program::initClBinary(const char* binaryIn, size_t size, amd::Os::FileDesc fdesc, + size_t foffset, std::string uri) { if (!initClBinary()) { DevLogError("Init CL Binary failed \n"); return false; @@ -1947,12 +1950,13 @@ bool Program::initClBinary(const char* binaryIn, size_t size) { clBinary()->setFlags(encryptCode); - return clBinary()->setBinary(bin, sz, (decryptedBin != nullptr)); + return clBinary()->setBinary(bin, sz, (decryptedBin != nullptr), fdesc, foffset, uri); } // ================================================================================================ -bool Program::setBinary(const char* binaryIn, size_t size, const device::Program* same_dev_prog) { - if (!initClBinary(binaryIn, size)) { +bool Program::setBinary(const char* binaryIn, size_t size, const device::Program* same_dev_prog, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { + if (!initClBinary(binaryIn, size, fdesc, foffset, uri)) { DevLogError("Init CL Binary failed \n"); return false; } @@ -2187,6 +2191,8 @@ aclType Program::getCompilationStagesFromBinary(std::vector& completeSt aclType Program::getNextCompilationStageFromBinary(amd::option::Options* options) { aclType continueCompileFrom = ACL_TYPE_DEFAULT; binary_t binary = this->binary(); + finfo_t finfo = this->BinaryFd(); + std::string uri = this->BinaryURI(); // If the binary already exists if ((binary.first != nullptr) && (binary.second > 0)) { #if defined(WITH_COMPILER_LIB) @@ -2207,7 +2213,8 @@ aclType Program::getNextCompilationStageFromBinary(amd::option::Options* options // Saving binary in the interface class, // which also load compile & link options from binary - setBinary(static_cast(binary.first), binary.second); + setBinary(static_cast(binary.first), binary.second, nullptr, + finfo.first, finfo.second, uri); // Calculate the next stage to compile from, based on sections in binaryElf_; // No any validity checks here diff --git a/rocclr/device/devprogram.hpp b/rocclr/device/devprogram.hpp index de38bd31ee..90f261f80f 100755 --- a/rocclr/device/devprogram.hpp +++ b/rocclr/device/devprogram.hpp @@ -70,7 +70,8 @@ struct SymbolLoweredName { //! A program object for a specific device. class Program : public amd::HeapObject { public: - typedef std::pair binary_t; + typedef std::pair binary_t; + typedef std::pair finfo_t; typedef std::unordered_map kernels_t; // type of the program typedef enum { @@ -186,12 +187,15 @@ class Program : public amd::HeapObject { //! 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); + bool setBinary(const char* binaryIn, size_t size, const device::Program* same_dev_prog = nullptr, + amd::Os::FileDesc fdesc = -1, size_t foffset = 0, std::string uri = std::string()); type_t type() const { return type_; } @@ -279,7 +283,8 @@ class Program : public amd::HeapObject { virtual bool createBinary(amd::option::Options* options) = 0; //! Initialize Binary (used only for clCreateProgramWithBinary()). - bool initClBinary(const char* binaryIn, size_t size); + bool initClBinary(const char* binaryIn, size_t size, amd::Os::FileDesc fdesc = -1, + size_t foffset = 0, std::string uri = std::string()); //! Initialize Binary virtual bool initClBinary(); @@ -293,7 +298,9 @@ class Program : public amd::HeapObject { virtual const aclTargetInfo& info(const char* str = "") = 0; virtual bool setKernels( - amd::option::Options* options, void* binary, size_t binSize) { return true; } + amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc = -1, 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 ProcessOptions(amd::option::Options* options); diff --git a/rocclr/device/pal/palprogram.cpp b/rocclr/device/pal/palprogram.cpp old mode 100644 new mode 100755 index 19d94081bc..536eba3e80 --- a/rocclr/device/pal/palprogram.cpp +++ b/rocclr/device/pal/palprogram.cpp @@ -238,7 +238,8 @@ inline static std::vector splitSpaceSeparatedString(char* str) { return vec; } -bool HSAILProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize) { +bool HSAILProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { #if defined(WITH_COMPILER_LIB) // ACL_TYPE_CG stage is not performed for offline compilation hsa_agent_t agent; @@ -735,7 +736,8 @@ bool LightningProgram::createBinary(amd::option::Options* options) { return true; } -bool LightningProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize) { +bool LightningProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { #if defined(USE_COMGR_LIBRARY) hsa_agent_t agent; agent.handle = 1; diff --git a/rocclr/device/pal/palprogram.hpp b/rocclr/device/pal/palprogram.hpp old mode 100644 new mode 100755 index f69c37e786..865155ec6e --- a/rocclr/device/pal/palprogram.hpp +++ b/rocclr/device/pal/palprogram.hpp @@ -195,7 +195,9 @@ class HSAILProgram : public device::Program { virtual const aclTargetInfo& info(const char* str = ""); - virtual bool setKernels(amd::option::Options* options, void* binary, size_t binSize) override; + virtual bool setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc = -1, size_t foffset = 0, + std::string uri = std::string()) override; //! Destroys CPU allocations in the code segment void DestroySegmentCpuAccess() const { diff --git a/rocclr/device/rocm/rocprogram.cpp b/rocclr/device/rocm/rocprogram.cpp old mode 100644 new mode 100755 index 1280286e5f..70758d6a35 --- a/rocclr/device/rocm/rocprogram.cpp +++ b/rocclr/device/rocm/rocprogram.cpp @@ -264,7 +264,8 @@ bool HSAILProgram::saveBinaryAndSetType(type_t type) { return true; } -bool HSAILProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize) { +bool HSAILProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { #if defined(WITH_COMPILER_LIB) // Stop compilation if it is an offline device - HSA runtime does not // support ISA compiled offline @@ -467,7 +468,8 @@ bool LightningProgram::saveBinaryAndSetType(type_t type, void* rawBinary, size_t return true; } -bool LightningProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize) { +bool LightningProgram::setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc, size_t foffset, std::string uri) { #if defined(USE_COMGR_LIBRARY) // Find the size of global variables from the binary if (!FindGlobalVarSize(binary, binSize)) { @@ -488,7 +490,9 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s return false; } - // Load the code object. + // Load the code object, either with file descriptor and offset + // or binary image and binary size with URI + // or binary image and binary size status = hsa_code_object_reader_create_from_memory(binary, binSize, &hsaCodeObjectReader_); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: AMD HSA Code Object Reader create failed: "; diff --git a/rocclr/device/rocm/rocprogram.hpp b/rocclr/device/rocm/rocprogram.hpp old mode 100644 new mode 100755 index ba99553d05..ca71000178 --- a/rocclr/device/rocm/rocprogram.hpp +++ b/rocclr/device/rocm/rocprogram.hpp @@ -91,7 +91,9 @@ class HSAILProgram : public roc::Program { protected: bool createBinary(amd::option::Options* options) override { return true; } - virtual bool setKernels(amd::option::Options* options, void* binary, size_t binSize) override; + virtual bool setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc = -1, size_t foffset = 0, + std::string uri = std::string()) override; private: std::string codegenOptions(amd::option::Options* options); @@ -112,7 +114,9 @@ protected: private: bool saveBinaryAndSetType(type_t type, void* rawBinary, size_t size); - bool setKernels(amd::option::Options* options, void* binary, size_t binSize) final; + bool setKernels(amd::option::Options* options, void* binary, size_t binSize, + amd::Os::FileDesc fdesc = -1, size_t foffset = 0, + std::string uri = std::string()) final; }; /*@}*/} // namespace roc diff --git a/rocclr/os/os.cpp b/rocclr/os/os.cpp old mode 100644 new mode 100755 diff --git a/rocclr/os/os.hpp b/rocclr/os/os.hpp old mode 100644 new mode 100755 index 65f5d0cefe..5f4c5d234a --- a/rocclr/os/os.hpp +++ b/rocclr/os/os.hpp @@ -52,6 +52,14 @@ class Thread; // For Os::createOsThread() class Os : AllStatic { public: + +// File Desc abstraction between OS +#if defined(_WIN32) + typedef HANDLE FileDesc; +#else + typedef int FileDesc; +#endif + enum MemProt { MEM_PROT_NONE = 0, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX }; class ThreadAffinityMask { @@ -91,7 +99,20 @@ class Os : AllStatic { #endif }; + // Returns unique resource indicator for a particular memory + static bool GetURIFromMemory(const void* image, size_t image_size, std::string& uri); + + // Closes the file Handle + static bool CloseFileHandle(FileDesc fdesc); + // Given a valid file name, returns file descriptor and file size + static bool GetFileHandle(const char* fname, FileDesc* fd_ptr, size_t* sz_ptr); + + // Given a valid file descriptor returns mmaped memory for size and offset + static bool MemoryMapFileDesc(FileDesc fdesc, size_t fsize, size_t foffset, + const void** mmap_ptr); + // Given a valid file name, returns mmapped memory with the mapped size. static bool MemoryMapFile(const char* fname, const void** mmap_ptr, size_t* mmap_size); + // Given a valid mmaped ptr with correct size, unmaps the ptr from memory static bool MemoryUnmapFile(const void* mmap_ptr, size_t mmap_size); private: diff --git a/rocclr/os/os_posix.cpp b/rocclr/os/os_posix.cpp index a0307d806c..91d08bc3d0 100755 --- a/rocclr/os/os_posix.cpp +++ b/rocclr/os/os_posix.cpp @@ -716,8 +716,69 @@ void Os::getAppPathAndFileName(std::string& appName, std::string& appPathAndName return; } + +bool Os::GetURIFromMemory(const void* image, size_t image_size, std::string& uri) { + pid_t pid = getpid(); + std::ostringstream uri_stream; + //Create a unique resource indicator to the memory address + uri_stream << "memory://" << pid + << "#offset=0x" << std::hex << (uintptr_t)image << std::dec + << "&size=" << image_size; + uri = uri_stream.str(); + return true; +} + +bool Os::CloseFileHandle(FileDesc fdesc) { + // Return false if close system call fails + if(close(fdesc) < 0) { + return false; + } + + return true; +} + +bool Os::GetFileHandle(const char* fname, FileDesc* fd_ptr, size_t* sz_ptr) { + if ((fd_ptr == nullptr) || (sz_ptr == nullptr)) { + return false; + } + + // open system function call, return false on fail + struct stat stat_buf; + *fd_ptr = open(fname, O_RDONLY); + if (*fd_ptr < 0) { + return false; + } + + //Retrieve stat info and size + if (fstat(*fd_ptr, &stat_buf) != 0) { + close(*fd_ptr); + return false; + } + + *sz_ptr = stat_buf.st_size; + + return true; +} + +bool Os::MemoryMapFileDesc(FileDesc fdesc, size_t fsize, size_t foffset, const void** mmap_ptr) { + if (fdesc <= 0) { + return false; + } + + // If the offset is not aligned then align it + // and recalculate the new size + if (foffset > 0) { + size_t old_foffset = foffset; + foffset = alignUp(foffset, pageSize()); + fsize += (foffset - old_foffset); + } + + *mmap_ptr = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdesc, foffset); + return true; +} + bool Os::MemoryUnmapFile(const void* mmap_ptr, size_t mmap_size) { - if(munmap(const_cast(mmap_ptr), mmap_size) != 0) { + if (munmap(const_cast(mmap_ptr), mmap_size) != 0) { return false; } @@ -735,7 +796,7 @@ bool Os::MemoryMapFile(const char* fname, const void** mmap_ptr, size_t* mmap_si return false; } - if(fstat(fd, &stat_buf) != 0) { + if (fstat(fd, &stat_buf) != 0) { close(fd); return false; } diff --git a/rocclr/os/os_win32.cpp b/rocclr/os/os_win32.cpp old mode 100644 new mode 100755 index c8df137626..3c92bd6072 --- a/rocclr/os/os_win32.cpp +++ b/rocclr/os/os_win32.cpp @@ -822,6 +822,50 @@ void Os::getAppPathAndFileName(std::string& appName, std::string& appPathAndName return; } +bool Os::GetURIFromMemory(const void* image, size_t image_size, std::string& uri_) { + // Not implemented yet for windows + uri = std::string(); + return true; +} + +bool Os::CloseFileHandle(FileDesc fdesc) { + // return false on failure + if (CloseHandle(fdesc) < 0) { + return false; + } + return true; +} + +bool GetFileHandle(const char* fname, FileDesc* fd_ptr, size_t* sz_ptr) { + if ((fd_ptr == nullptr) || (sz_ptr == nullptr)) { + return false; + } + + *fd_ptr = INVALID_HANDLE_VALUE; + *fd_ptr = CreateFileA(fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, NULL); + if (*fd_ptr == INVALID_HANDLE_VALUE) { + return false; + } + + *sz_ptr = GetFileSize(*fd_ptr, NULL); + return true; +} + +bool MemoryMapFileDesc(FileDesc fdesc, size_t fsize, size_t foffset, const void** mmap_ptr) { + if (fdesc < 0) { + return false; + } + + *mmap_ptr = INVALID_HANDLE_VALUE; + *mmap_ptr = CreateFileMappingA(fdesc, NULL, PAGE_READONLY, 0, 0, NULL); + if (*mmap_ptr == INVALID_HANDLE_VALUE) { + return false; + } + + return true; +} + bool Os::MemoryUnmapFile(const void* mmap_ptr, size_t mmap_size) { if(!UnmapViewOfFile(mmap_ptr)) { return false; diff --git a/rocclr/platform/program.cpp b/rocclr/platform/program.cpp index ee5cdea926..b12c93f086 100755 --- a/rocclr/platform/program.cpp +++ b/rocclr/platform/program.cpp @@ -67,10 +67,6 @@ Program::~Program() { } } - if (std::get<1>(mmap_) > 0) { - amd::Os::MemoryUnmapFile(std::get<0>(mmap_), std::get<1>(mmap_)); - } - delete symbolTable_; //! @todo Make sure we have destroyed all CPU specific objects } @@ -86,9 +82,10 @@ const Symbol* Program::findSymbol(const char* kernelName) const { } int32_t Program::addDeviceProgram(Device& device, const void* image, size_t length, - bool make_copy, amd::option::Options* options, - const amd::Program* same_prog) { - if (image != nullptr && !amd::Elf::isElfMagic((const char*)image)) { + bool make_copy, amd::option::Options* options, + const amd::Program* same_prog, amd::Os::FileDesc fdesc, + size_t foffset, std::string uri) { + if (image != NULL && !amd::Elf::isElfMagic((const char*)image)) { if (device.settings().useLightning_) { return CL_INVALID_BINARY; } @@ -167,8 +164,7 @@ int32_t Program::addDeviceProgram(Device& device, const void* image, size_t leng ::memcpy(image_copy, image, length); memory = image_copy; - } - else { + } else { memory = static_cast(image); } @@ -183,7 +179,8 @@ int32_t Program::addDeviceProgram(Device& device, const void* image, size_t leng same_dev_prog = same_dev_prog_map_.begin()->second; } - if (!program->setBinary(reinterpret_cast(memory), length, same_dev_prog)) { + if (!program->setBinary(reinterpret_cast(memory), length, same_dev_prog, + fdesc, foffset, uri)) { delete program; return CL_INVALID_BINARY; } diff --git a/rocclr/platform/program.hpp b/rocclr/platform/program.hpp index ce6b6ba72e..36289139f6 100755 --- a/rocclr/platform/program.hpp +++ b/rocclr/platform/program.hpp @@ -80,7 +80,6 @@ class Context; //! A collection of binaries for devices in the associated context. class Program : public RuntimeObject { public: - typedef std::pair mmap_t; typedef std::tuple binary_t; typedef std::set devicelist_t; typedef std::unordered_map devicebinary_t; @@ -114,7 +113,6 @@ class Program : public RuntimeObject { //! The device program objects included in this program deviceprograms_t devicePrograms_; devicelist_t deviceList_; - const mmap_t mmap_; std::string programLog_; //!< Log for parsing options, etc. @@ -135,16 +133,13 @@ class Program : public RuntimeObject { sourceCode_(sourceCode), language_(language), symbolTable_(NULL), - mmap_({nullptr, 0}), programLog_() { } //! Construct a new program associated with a context. - Program(Context& context, Language language = Binary, - const void* mmap_ptr = nullptr, const size_t mmap_size = 0) + Program(Context& context, Language language = Binary) : context_(context), language_(language), - symbolTable_(NULL), - mmap_({mmap_ptr, mmap_size}) {} + symbolTable_(NULL) {} //! Returns context, associated with the current program. const Context& context() const { return context_(); } @@ -175,8 +170,9 @@ class Program : public RuntimeObject { //! Add a new device program with or without binary image and options. int32_t addDeviceProgram(Device&, const void* image = NULL, size_t len = 0, - bool make_copy = true, amd::option::Options* options = NULL, - const amd::Program* same_prog = nullptr); + bool make_copy = true, amd::option::Options* options = NULL, + const amd::Program* same_prog = nullptr, amd::Os::FileDesc fdesc = -1, + size_t foffset = 0, std::string uri = std::string()); //! Find the section for the given device. Return NULL if not found. device::Program* getDeviceProgram(const Device& device) const;