Index: clang/tools/clang-offload-wrapper/ClangOffloadWrapper.cpp =================================================================== --- clang/tools/clang-offload-wrapper/ClangOffloadWrapper.cpp +++ clang/tools/clang-offload-wrapper/ClangOffloadWrapper.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include @@ -59,6 +60,33 @@ cl::desc("Target triple for the output module"), cl::value_desc("triple"), cl::cat(ClangOffloadWrapperCategory)); +// FIXME: set version in CMake. +#define getOpenMPOffloadVersionString() std::string("unknown") + +LLVM_YAML_STRONG_TYPEDEF(std::string, OpenMPAttrTy) +LLVM_YAML_IS_SEQUENCE_VECTOR(OpenMPAttrTy) + +namespace llvm { +namespace yaml { +template <> struct ScalarTraits { + static void output(const OpenMPAttrTy &Val, void *, raw_ostream &Out) { + Out << Val; + } + static StringRef input(StringRef Scalar, void *, OpenMPAttrTy &Val) { + Val = Scalar.str(); + return StringRef(); + } + static QuotingType mustQuote(StringRef) { return QuotingType::Double; } +}; +} // end namespace yaml +} // end namespace llvm + +typedef SmallVector OpenMPAttrListTy; +LLVM_YAML_IS_STRING_MAP(OpenMPAttrListTy) + +typedef std::map OpenMPAttrDocTy; +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(OpenMPAttrDocTy) + namespace { class BinaryWrapper { @@ -202,13 +230,75 @@ SmallVector ImagesInits; ImagesInits.reserve(Bufs.size()); for (ArrayRef Buf : Bufs) { - auto *Data = ConstantDataArray::get(C, Buf); + SmallVector ImageBuf; + + // Insert 1OMP header magic word. + // The expected image structure is like this: + // struct { + // char MagicWord[ONEOMPMAGLEN]; // "1OMP" + // uint32_t HeaderSize; // In little-endian. + // char Header[HeaderSize]; // Uncompressed YAML with auxiliary + // // information. + // char ActualImage[]; // ELF or another image. + // } + StringRef Header("1OMP"); + ImageBuf.append(Header.begin(), Header.end()); + // Reserve 4 bytes for the header size. + ImageBuf.append(4, '\0'); + + size_t HeaderBegin = ImageBuf.size(); + raw_svector_ostream YamlOS(ImageBuf); + yaml::Output YamlOut(YamlOS, NULL, 0); + + SmallVector Attrs; + Attrs.push_back(OpenMPAttrDocTy()); + OpenMPAttrDocTy &Doc = Attrs[0]; + // TODO: different vendors will use different names + // from OpenMP API Additional Definitions 2.0. + Doc["VendorName"].push_back(std::string("llvm")); + Doc["VendorId"].push_back(std::string("9")); + Doc["Producer"].push_back(getOpenMPOffloadVersionString()); + // TODO: support clang-offload-wrapper option that specifies + // target triple per the offload image. + Doc["TargetID"].push_back(std::string("")); + // TODO: support clang-offload-wrapper options that specify + // CompileOptions/LinkOptions per the offload image. + // Alternatively, driver may pass a YAML file specifying + // the whole context for the wrapping that needs to be done. + Doc["CompileOptions"].push_back(std::string("")); + Doc["LinkOptions"].push_back(std::string("")); + + YamlOut << Attrs; + + size_t HeaderEnd = ImageBuf.size(); + size_t HeaderSize = HeaderEnd - HeaderBegin; + assert(HeaderSize <= (std::numeric_limits::max)() && + "1OMP header is too big."); + // Set proper header size, which is in little-endian format. + ImageBuf[HeaderBegin - 4] = (HeaderSize & 0xFF); + ImageBuf[HeaderBegin - 3] = ((HeaderSize >> 8) & 0xFF); + ImageBuf[HeaderBegin - 2] = ((HeaderSize >> 16) & 0xFF); + ImageBuf[HeaderBegin - 1] = ((HeaderSize >> 24) & 0xFF); + + const char *BufStart = Buf.data(); + size_t BufSize = Buf.size(); + if (ImageBuf.size() > 0) { + // Concatenate data. + // + // FIXME: we have to find a way to avoid copying the image + // twice. + ImageBuf.append(Buf.begin(), Buf.end()); + BufStart = ImageBuf.data(); + BufSize = ImageBuf.size(); + } + + auto *Data = ConstantDataArray::get(C, makeArrayRef(BufStart, BufSize)); auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant*/ true, GlobalVariable::InternalLinkage, Data, ".omp_offloading.device_image"); Image->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - auto *Size = ConstantInt::get(getSizeTTy(), Buf.size()); + auto *Size = ConstantInt::get(getSizeTTy(), BufSize); Constant *ZeroSize[] = {Zero, Size}; auto *ImageB = ConstantExpr::getGetElementPtr(Image->getValueType(), Index: openmp/libomptarget/plugins/CMakeLists.txt =================================================================== --- openmp/libomptarget/plugins/CMakeLists.txt +++ openmp/libomptarget/plugins/CMakeLists.txt @@ -48,6 +48,19 @@ dl "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports") + if (NOT OPENMP_STANDALONE_BUILD) + # FIXME: we should probably require pre-built LLVM project + # to be available, otherwise, in-tree and out-of-tree + # builds of libomptarget will behave quite differently. + # Alternatively, we can link to some YAML parsing library + # statically, and require it to be available during + # libomptarget build (e.g. LibYAML is under MIT license). + target_link_libraries( + "omptarget.rtl.${tmachine_libname}" + LLVMSupport + ) + endif() + list(APPEND LIBOMPTARGET_TESTED_PLUGINS "omptarget.rtl.${tmachine_libname}") @@ -68,6 +81,10 @@ endif() endmacro() +if (NOT OPENMP_STANDALONE_BUILD) + add_definitions(-DOPENMP_MAY_USE_LLVM_SUPPORT) +endif() + add_subdirectory(aarch64) add_subdirectory(cuda) add_subdirectory(ppc64) Index: openmp/libomptarget/plugins/amdgpu/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins/amdgpu/src/rtl.cpp +++ openmp/libomptarget/plugins/amdgpu/src/rtl.cpp @@ -638,6 +638,14 @@ } bool elf_machine_id_is_amdgcn(__tgt_device_image *image) { + // TODO: this AuxInfo is just being discarded, + // and we need to do something better. + std::vector AuxInfo; + if (!getAuxInfo(image, AuxInfo)) + return 0; + dumpAuxInfo(AuxInfo); + // TODO: VendorName, VendorID, Producer and TargetID checks may be done here + // by particular plugins (e.g. via calling specific API). const uint16_t amdgcnMachineID = 224; // EM_AMDGPU may not be in system elf.h int32_t r = elf_check_machine(image, amdgcnMachineID); if (!r) { @@ -647,7 +655,7 @@ } uint32_t elf_e_flags(__tgt_device_image *image) { - char *img_begin = (char *)image->ImageStart; + char *img_begin = getImageStart(image); size_t img_size = (char *)image->ImageEnd - img_begin; Elf *e = elf_memory(img_begin, img_size); @@ -1050,7 +1058,7 @@ } #endif - int rc = get_symbol_info_without_loading((char *)image->ImageStart, + int rc = get_symbol_info_without_loading(getImageStart(image), img_size, sym(), &si); if (rc != 0) { DP("Finding global device environment '%s' - symbol missing.\n", sym()); @@ -1072,7 +1080,7 @@ assert(valid); if (in_image()) { DP("Setting global device environment before load (%u bytes)\n", si.size); - uint64_t offset = (char *)si.addr - (char *)image->ImageStart; + uint64_t offset = (char *)si.addr - getImageStart(image); void *pos = (char *)data + offset; memcpy(pos, &host_device_env, si.size); } @@ -1151,7 +1159,15 @@ // runtime behaviour. E.g. launching a kernel or using dma to get eight bytes // back from the gpu vs a hashtable lookup on the host. - const size_t img_size = (char *)image->ImageEnd - (char *)image->ImageStart; + if (!getAuxInfo(image, DeviceInfo.AuxInfo)) { + DP("Failed to read auxiliary information!\n"); + return NULL; + } + // TODO: use the auxiliary information for the image processing. + // For example, may the whole "omptarget_device_environment" + // be embedded into the auxiliary info? + char *img_begin = getImageStart(image); + const size_t img_size = (char *)image->ImageEnd - img_begin; DeviceInfo.clearOffloadEntriesTable(device_id); @@ -1170,7 +1186,7 @@ } atmi_status_t err = module_register_from_memory_to_place( - (void *)image->ImageStart, img_size, get_gpu_place(device_id), + (void *)img_begin, img_size, get_gpu_place(device_id), [&](void *data, size_t size) { return env.before_loading(data, size); }); @@ -1219,7 +1235,7 @@ // sizeof(void*) if (state_ptr_size == sizeof(void *)) { uint64_t device_State_bytes = - get_device_State_bytes((char *)image->ImageStart, img_size); + get_device_State_bytes(img_begin, img_size); if (device_State_bytes == 0) { return NULL; } @@ -1358,7 +1374,7 @@ void *KernDescPtr; uint32_t KernDescSize; void *CallStackAddr = nullptr; - err = interop_get_symbol_info((char *)image->ImageStart, img_size, + err = interop_get_symbol_info(img_begin, img_size, KernDescName, &KernDescPtr, &KernDescSize); if (err == ATMI_STATUS_SUCCESS) { @@ -1400,7 +1416,7 @@ void *ExecModePtr; uint32_t varsize; - err = interop_get_symbol_info((char *)image->ImageStart, img_size, + err = interop_get_symbol_info(img_begin, img_size, ExecModeName, &ExecModePtr, &varsize); if (err == ATMI_STATUS_SUCCESS) { @@ -1437,7 +1453,7 @@ void *WGSizePtr; uint32_t WGSize; - err = interop_get_symbol_info((char *)image->ImageStart, img_size, + err = interop_get_symbol_info(img_begin, img_size, WGSizeName, &WGSizePtr, &WGSize); if (err == ATMI_STATUS_SUCCESS) { Index: openmp/libomptarget/plugins/common/CMakeLists.txt =================================================================== --- openmp/libomptarget/plugins/common/CMakeLists.txt +++ openmp/libomptarget/plugins/common/CMakeLists.txt @@ -10,5 +10,6 @@ # ##===----------------------------------------------------------------------===## +add_subdirectory(tgt_image) add_subdirectory(elf_common) add_subdirectory(MemoryManager) Index: openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt =================================================================== --- openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt +++ openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt @@ -11,5 +11,6 @@ ##===----------------------------------------------------------------------===## add_library(elf_common INTERFACE) +target_link_libraries(elf_common INTERFACE tgt_image_common) target_include_directories(elf_common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) Index: openmp/libomptarget/plugins/common/elf_common/elf_common.h =================================================================== --- openmp/libomptarget/plugins/common/elf_common/elf_common.h +++ openmp/libomptarget/plugins/common/elf_common/elf_common.h @@ -20,6 +20,7 @@ #include #include +#include "tgt_image_common.h" // Check whether an image is valid for execution on target_id static inline int32_t elf_check_machine(__tgt_device_image *image, @@ -31,7 +32,7 @@ return 0; } - char *img_begin = (char *)image->ImageStart; + char *img_begin = getImageStart(image); char *img_end = (char *)image->ImageEnd; size_t img_size = img_end - img_begin; @@ -74,7 +75,7 @@ static inline int32_t elf_is_dynamic(__tgt_device_image *image) { - char *img_begin = (char *)image->ImageStart; + char *img_begin = getImageStart(image); char *img_end = (char *)image->ImageEnd; size_t img_size = img_end - img_begin; Index: openmp/libomptarget/plugins/common/tgt_image/CMakeLists.txt =================================================================== --- /dev/null +++ openmp/libomptarget/plugins/common/tgt_image/CMakeLists.txt @@ -0,0 +1,14 @@ +##===----------------------------------------------------------------------===## +# +# 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 +# +##===----------------------------------------------------------------------===## +# +# Common parts which can be used by all plugins +# +##===----------------------------------------------------------------------===## + +add_library(tgt_image_common INTERFACE) +target_include_directories(tgt_image_common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) Index: openmp/libomptarget/plugins/common/tgt_image/tgt_image_common.h =================================================================== --- /dev/null +++ openmp/libomptarget/plugins/common/tgt_image/tgt_image_common.h @@ -0,0 +1,169 @@ +//===-- tgt_image_common.h - Common target image functionality --*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Common functionality for processing target images in target plugins. +// Must be included in the plugin source file AFTER omptarget.h has been +// included and macro DP(...) has been defined. +// . +// +//===----------------------------------------------------------------------===// + +#if !(defined(_OMPTARGET_DEBUG_H)) +#error Include common.cpp in the plugin source AFTER Debug.h has been included. +#endif + +#include +#include +#include +#if OPENMP_MAY_USE_LLVM_SUPPORT +#include "llvm/Support/YAMLTraits.h" +#endif // OPENMP_MAY_USE_LLVM_SUPPORT + +#define ONEOMPMAGLEN 4 +#define ONEOMPMAG "1OMP" + +struct OpenMPHeaderDesc { + char *Begin; + uint32_t Size; +}; + +static inline char *getImageStart( + const __tgt_device_image *Image, + OpenMPHeaderDesc *HeaderDesc = nullptr) { + char *ImageStart = (char *)Image->ImageStart; + char *ImageEnd = (char *)Image->ImageEnd; + + if (HeaderDesc) { + HeaderDesc->Begin = nullptr; + HeaderDesc->Size = 0; + } + + if (ImageEnd - ImageStart < ONEOMPMAGLEN) + return ImageStart; + + if (std::memcmp((void *)ImageStart, ONEOMPMAG, ONEOMPMAGLEN) != 0) + return ImageStart; + + // "1OMP" magic word. + // The expected image structure is like this: + // struct { + // char MagicWord[ONEOMPMAGLEN]; // "1OMP" + // uint32_t HeaderSize; // In little-endian. + // char Header[HeaderSize]; // Uncompressed YAML with auxiliary + // // information. + // char ActualImage[]; // ELF or another image. + // } + uint32_t HeaderSize = *(uint32_t *)((char *)ImageStart + ONEOMPMAGLEN); + char *HeaderBegin = ImageStart + ONEOMPMAGLEN + sizeof(uint32_t); + ImageStart = HeaderBegin + HeaderSize; + DP("1OMP header: HeaderSize(%" PRIu32 "), HeaderBegin(" + DPxMOD "), ImageBegin(" DPxMOD "), ImageEnd(" DPxMOD ")\n", + HeaderSize, DPxPTR(HeaderBegin), DPxPTR(ImageStart), DPxPTR(ImageEnd)); + + if (ImageStart > ImageEnd) { + FAILURE_MESSAGE("HeaderSize (%" PRIu32 ") is too big\n", HeaderSize); + FATAL_MESSAGE0(0, "invalid 1OMP image"); + } + + if (HeaderDesc) { + HeaderDesc->Begin = HeaderBegin; + HeaderDesc->Size = HeaderSize; + } + + return ImageStart; +} + +#if OPENMP_MAY_USE_LLVM_SUPPORT +using namespace llvm; + +LLVM_YAML_STRONG_TYPEDEF(std::string, OpenMPAttrTy) +LLVM_YAML_IS_SEQUENCE_VECTOR(OpenMPAttrTy) + +namespace llvm { +namespace yaml { +template <> struct ScalarTraits { + static void output(const OpenMPAttrTy &Val, void *, raw_ostream &Out) { + Out << Val; + } + static StringRef input(StringRef Scalar, void *, OpenMPAttrTy &Val) { + Val = Scalar.str(); + return StringRef(); + } + static QuotingType mustQuote(StringRef) { return QuotingType::Double; } +}; +} // end namespace yaml +} // end namespace llvm +#else // !OPENMP_MAY_USE_LLVM_SUPPORT +typedef std::string OpenMPAttrTy; +#endif // !OPENMP_MAY_USE_LLVM_SUPPORT + +typedef std::vector OpenMPAttrListTy; +typedef std::map OpenMPAttrDocTy; + +#if OPENMP_MAY_USE_LLVM_SUPPORT +LLVM_YAML_IS_STRING_MAP(OpenMPAttrListTy) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(OpenMPAttrDocTy) +#endif // OPENMP_MAY_USE_LLVM_SUPPORT + +static inline bool getAuxInfo( + const __tgt_device_image *Image, + std::vector &Out) { + OpenMPHeaderDesc HeaderDesc; + getImageStart(Image, &HeaderDesc); + if (!HeaderDesc.Size) { + if (!HeaderDesc.Begin) { + // If there is no 1OMP header, then we may assume we successfully + // read the auxiliary information, which is none. + // + // This may happen with older binaries, which are supported + // by the legacy ELF path. + return true; + } else { + // There is 1OMP header with 0 size. + // This is unexpected, since there are mandatory members + // like VendorName, VendorID and Producer. + return false; + } + } + + // There 1OMP header, so we have to either read it successfully + // or return false. +#if !OPENMP_MAY_USE_LLVM_SUPPORT + return false; +#else // OPENMP_MAY_USE_LLVM_SUPPORT + StringRef HeaderBuf(HeaderDesc.Begin, HeaderDesc.Size); + yaml::Input YamlIn(HeaderBuf); + std::vector Docs; + YamlIn >> Out; + + if (std::error_code Err = YamlIn.error()) { + FAILURE_MESSAGE("1OMP YAML reading failed\n"); + return false; + } + + return true; +#endif // OPENMP_MAY_USE_LLVM_SUPPORT +} + +static inline void dumpAuxInfo(const std::vector &Info) { +#if OMPTARGET_DEBUG + if (!Info.empty()) { + for (auto &Doc : Info) { + for (auto &Attr : Doc) { + DP("Read OpenMPAttr:\n"); + DP("<%s: [\n", Attr.first.c_str()); + for (auto &Val : Attr.second) { + const std::string &Str = Val; + DP("\t%s,\n", Str.c_str()); + } + DP("]>\n"); + } + } + } +#endif // OMPTARGET_DEBUG +} Index: openmp/libomptarget/plugins/cuda/CMakeLists.txt =================================================================== --- openmp/libomptarget/plugins/cuda/CMakeLists.txt +++ openmp/libomptarget/plugins/cuda/CMakeLists.txt @@ -55,6 +55,13 @@ "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" "-Wl,-z,defs") +if (NOT OPENMP_STANDALONE_BUILD) + target_link_libraries( + omptarget.rtl.cuda + LLVMSupport + ) +endif() + # Report to the parent scope that we are building a plugin for CUDA. # This controls whether tests are run for the nvptx offloading target # Run them if libcuda is available, or if the user explicitly asked for dlopen Index: openmp/libomptarget/plugins/cuda/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins/cuda/src/rtl.cpp +++ openmp/libomptarget/plugins/cuda/src/rtl.cpp @@ -341,6 +341,9 @@ /// Whether use memory manager bool UseMemoryManager = true; + /// Auxiliary information associated with the device image. + std::vector AuxInfo; + // Record entry point associated with device void addOffloadEntry(const int DeviceId, const __tgt_offload_entry entry) { FuncOrGblEntryTy &E = DeviceData[DeviceId].FuncGblEntries.back(); @@ -624,6 +627,14 @@ __tgt_target_table *loadBinary(const int DeviceId, const __tgt_device_image *Image) { + if (!getAuxInfo(Image, AuxInfo)) { + DP("Failed to read auxiliary information!\n"); + return nullptr; + } + // TODO: use the auxiliary information for the image processing. + // For example, pass CompileOptions/LinkOptions + // to cuModuleLoadDataEx below. + void *ImageStart = getImageStart(Image); // Set the context we are using CUresult Err = cuCtxSetCurrent(DeviceData[DeviceId].Context); if (!checkResult(Err, "Error returned from cuCtxSetCurrent\n")) @@ -634,8 +645,8 @@ // Create the module and extract the function pointers. CUmodule Module; - DP("Load data from image " DPxMOD "\n", DPxPTR(Image->ImageStart)); - Err = cuModuleLoadDataEx(&Module, Image->ImageStart, 0, nullptr, nullptr); + DP("Load data from image " DPxMOD "\n", DPxPTR(ImageStart)); + Err = cuModuleLoadDataEx(&Module, ImageStart, 0, nullptr, nullptr); if (!checkResult(Err, "Error returned from cuModuleLoadDataEx\n")) return nullptr; @@ -1063,6 +1074,14 @@ #endif int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *image) { + // TODO: this AuxInfo is just being discarded, + // and we need to do something better. + std::vector AuxInfo; + if (!getAuxInfo(image, AuxInfo)) + return 0; + dumpAuxInfo(AuxInfo); + // TODO: VendorName, VendorID, Producer and TargetID checks may be done here + // by particular plugins (e.g. via calling specific API). return elf_check_machine(image, /* EM_CUDA */ 190); } Index: openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp +++ openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp @@ -57,6 +57,9 @@ public: std::list DynLibs; + /// Auxiliary information associated with the device image. + std::vector AuxInfo; + // Record entry point associated with device. void createOffloadTable(int32_t device_id, __tgt_offload_entry *begin, __tgt_offload_entry *end) { @@ -120,6 +123,14 @@ #if TARGET_ELF_ID < 1 return 0; #else + // TODO: this AuxInfo is just being discarded, + // and we need to do something better. + std::vector AuxInfo; + if (!getAuxInfo(image, AuxInfo)) + return 0; + dumpAuxInfo(AuxInfo); + // TODO: VendorName, VendorID, Producer and TargetID checks may be done here + // by particular plugins (e.g. via calling specific API). return elf_check_machine(image, TARGET_ELF_ID); #endif } @@ -131,12 +142,18 @@ __tgt_target_table *__tgt_rtl_load_binary(int32_t device_id, __tgt_device_image *image) { + if (!getAuxInfo(image, DeviceInfo.AuxInfo)) { + DP("Failed to read auxiliary information!\n"); + return NULL; + } + // TODO: use the auxiliary information for the image processing. + char *img_begin = getImageStart(image); DP("Dev %d: load binary from " DPxMOD " image\n", device_id, - DPxPTR(image->ImageStart)); + DPxPTR(img_begin)); assert(device_id >= 0 && device_id < NUMBER_OF_DEVICES && "bad dev id"); - size_t ImageSize = (size_t)image->ImageEnd - (size_t)image->ImageStart; + size_t ImageSize = (size_t)image->ImageEnd - (size_t)img_begin; size_t NumEntries = (size_t)(image->EntriesEnd - image->EntriesBegin); DP("Expecting to have %zd entries defined.\n", NumEntries); @@ -147,7 +164,7 @@ } // Obtain elf handler - Elf *e = elf_memory((char *)image->ImageStart, ImageSize); + Elf *e = elf_memory(img_begin, ImageSize); if (!e) { DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1)); return NULL; @@ -210,7 +227,7 @@ return NULL; } - fwrite(image->ImageStart, ImageSize, 1, ftmp); + fwrite(img_begin, ImageSize, 1, ftmp); fclose(ftmp); DynLibTy Lib = {tmp_name, dlopen(tmp_name, RTLD_LAZY)}; Index: openmp/libomptarget/plugins/ve/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins/ve/src/rtl.cpp +++ openmp/libomptarget/plugins/ve/src/rtl.cpp @@ -60,6 +60,9 @@ // Maps OpenMP device Ids to Ve nodeids std::vector NodeIds; + /// Auxiliary information associated with the device image. + std::vector AuxInfo; + void buildOffloadTableFromHost(int32_t device_id, uint64_t VeoLibHandle, __tgt_offload_entry *HostBegin, __tgt_offload_entry *HostEnd) { @@ -192,6 +195,14 @@ #if TARGET_ELF_ID < 1 return 0; #else + // TODO: this AuxInfo is just being discarded, + // and we need to do something better. + std::vector AuxInfo; + if (!getAuxInfo(image, AuxInfo)) + return 0; + dumpAuxInfo(AuxInfo); + // TODO: VendorName, VendorID, Producer and TargetID checks may be done here + // by particular plugins (e.g. via calling specific API). return elf_check_machine(Image, TARGET_ELF_ID); #endif } @@ -218,12 +229,19 @@ // offload region is not supported on the target device. __tgt_target_table *__tgt_rtl_load_binary(int32_t ID, __tgt_device_image *Image) { + if (!getAuxInfo(image, DeviceInfo.AuxInfo)) { + DP("Failed to read auxiliary information!\n"); + return NULL; + } + // TODO: use the auxiliary information for the image processing. + char *ImageStart = getImageStart(image); + DP("Dev %d: load binary from " DPxMOD " image\n", ID, - DPxPTR(Image->ImageStart)); + DPxPTR(ImageStart)); assert(ID >= 0 && "bad dev id"); - size_t ImageSize = (size_t)Image->ImageEnd - (size_t)Image->ImageStart; + size_t ImageSize = (size_t)Image->ImageEnd - (size_t)ImageStart; size_t NumEntries = (size_t)(Image->EntriesEnd - Image->EntriesBegin); DP("Expecting to have %zd entries defined.\n", NumEntries); @@ -247,7 +265,7 @@ return NULL; } - fwrite(Image->ImageStart, ImageSize, 1, ftmp); + fwrite(ImageStart, ImageSize, 1, ftmp); // at least for the static case we need to change the permissions chmod(tmp_name, 0700);