// // Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved. // #include "api/v0_8/aclValidation.h" #include "libUtils.h" #include "bif/bifbase.hpp" #include "utils/target_mappings.h" #include "utils/versions.hpp" #include "utils/options.hpp" #include #include "bif/bif.hpp" extern aclBinary* constructBinary(size_t struct_version, const aclTargetInfo *target, const aclBinaryOptions *opts); static const std::string sgfx700 = "AMD:AMDGPU:7:0:0"; static const std::string sgfx701 = "AMD:AMDGPU:7:0:1"; static const std::string sgfx800 = "AMD:AMDGPU:8:0:0"; static const std::string sgfx801 = "AMD:AMDGPU:8:0:1"; static const std::string sgfx802 = "AMD:AMDGPU:8:0:2"; static const std::string sgfx803 = "AMD:AMDGPU:8:0:3"; static const std::string sgfx804 = "AMD:AMDGPU:8:0:4"; static const std::string sgfx810 = "AMD:AMDGPU:8:1:0"; static const std::string sgfx900 = "AMD:AMDGPU:9:0:0"; static const std::string sgfx901 = "AMD:AMDGPU:9:0:1"; static const std::string sgfx902 = "AMD:AMDGPU:9:0:2"; static const std::string sgfx903 = "AMD:AMDGPU:9:0:3"; static const std::string sgfx904 = "AMD:AMDGPU:9:0:4"; static const std::string sgfx905 = "AMD:AMDGPU:9:0:5"; static const std::string sgfx906 = "AMD:AMDGPU:9:0:6"; static const std::string sgfx907 = "AMD:AMDGPU:9:0:7"; static const std::string sgfx908 = "AMD:AMDGPU:9:0:8"; static const std::string sgfx1000 = "AMD:AMDGPU:10:0:0"; static const std::string sgfx1010 = "AMD:AMDGPU:10:1:0"; static const std::string sgfx1011 = "AMD:AMDGPU:10:1:1"; static const std::string sgfx1012 = "AMD:AMDGPU:10:1:2"; static const std::string legacyLibName = LINUX_ONLY("lib") "amdocl12cl" LP64_SWITCH(LINUX_SWITCH("32", ""), "64") LINUX_SWITCH(".so", ".dll"); // Utility function to set a flag in option structure // of the aclDevCaps. void setFlag(aclDevCaps *caps, compDeviceCaps option) { assert((uint32_t)option < ((1 << FLAG_SHIFT_VALUE) *FLAG_ARRAY_SIZE) && "The index passed in is outside of the range of valid values!"); caps->flags[option >> FLAG_SHIFT_VALUE] |= FLAG_BITLOC(option); } // Utility function to flip a flag in option structure // of the aclDevCaps. void flipFlag(aclDevCaps *caps, compDeviceCaps option) { assert((uint32_t)option < ((1 << FLAG_SHIFT_VALUE) *FLAG_ARRAY_SIZE) && "The index passed in is outside of the range of valid values!"); caps->flags[option >> FLAG_SHIFT_VALUE] ^= FLAG_BITLOC(option); } // Utility function to clear a flag in option structure // of the aclDevCaps. void clearFlag(aclDevCaps *caps, compDeviceCaps option) { assert((uint32_t)option < ((1 << FLAG_SHIFT_VALUE) *FLAG_ARRAY_SIZE) && "The index passed in is outside of the range of valid values!"); caps->flags[option >> FLAG_SHIFT_VALUE] &= ~FLAG_BITLOC(option); } // Utility function to check that a flag in option structure // of the aclDevCaps is set. bool checkFlag(aclDevCaps *caps, compDeviceCaps option) { assert((uint32_t)option < ((1 << FLAG_SHIFT_VALUE) *FLAG_ARRAY_SIZE) && "The index passed in is outside of the range of valid values!"); return ((uint32_t)(caps->flags[option >> FLAG_SHIFT_VALUE] & FLAG_BITLOC(option))) == (uint32_t)FLAG_BITLOC(option); } void setEncryptCaps(aclDevCaps_0_8 *ptr) { clearFlag(ptr, capSaveSOURCE); clearFlag(ptr, capSaveLLVMIR); clearFlag(ptr, capSaveCG); clearFlag(ptr, capSaveSPIR); clearFlag(ptr, capSaveAMDIL); clearFlag(ptr, capSaveHSAIL); clearFlag(ptr, capSaveDISASM); clearFlag(ptr, capSaveAS); setFlag(ptr, capSaveEXE); setFlag(ptr, capEncrypted); } void setOptionCaps(amd::option::Options *opts, aclDevCaps_0_8 *ptr) { #define COND_SET_FLAG(A) \ (((opts)->oVariables->Bin##A) ? setFlag(ptr, capSave##A) : clearFlag(ptr, capSave##A)) COND_SET_FLAG(SOURCE); COND_SET_FLAG(LLVMIR); COND_SET_FLAG(CG); COND_SET_FLAG(DISASM); COND_SET_FLAG(AMDIL); COND_SET_FLAG(HSAIL); COND_SET_FLAG(AS); COND_SET_FLAG(SPIR); COND_SET_FLAG(EXE); #undef COND_SET_FLAG } aclBIF *aclutGetBIF(aclBinary *binary) { aclBIF *bif = NULL; if (binary->struct_size == sizeof(aclBinary_0_8)) { bif = reinterpret_cast(binary)->bin; } else if (binary->struct_size == sizeof(aclBinary_0_8_1)) { bif = reinterpret_cast(binary)->bin; } else { assert(!"Binary format not supported!"); bif = reinterpret_cast(binary)->bin; } return bif; } aclOptions *aclutGetOptions(aclBinary *binary) { aclOptions *opt = NULL; if (binary->struct_size == sizeof(aclBinary_0_8)) { opt = reinterpret_cast(binary)->options; } else if (binary->struct_size == sizeof(aclBinary_0_8_1)) { opt = reinterpret_cast(binary)->options; } else { assert(!"Binary format not supported!"); opt = binary->options; } return opt; } aclBinaryOptions *aclutGetBinOpts(aclBinary *binary) { aclBinaryOptions *opt = NULL; if (binary->struct_size == sizeof(aclBinary_0_8)) { opt = reinterpret_cast( &reinterpret_cast(binary)->binOpts); } else if (binary->struct_size == sizeof(aclBinary_0_8_1)) { opt = &reinterpret_cast(binary)->binOpts; } else { assert(!"Binary format not supported!"); opt = &binary->binOpts; } return opt; } aclTargetInfo *aclutGetTargetInfo(aclBinary *binary) { aclTargetInfo *tgt = NULL; if (binary->struct_size == sizeof(aclBinary_0_8)) { tgt = &reinterpret_cast(binary)->target; } else if (binary->struct_size == sizeof(aclBinary_0_8_1)) { tgt = &reinterpret_cast(binary)->target; } else { assert(!"Binary format not supported!"); tgt = &binary->target; } return tgt; } aclDevCaps* aclutGetCaps(aclBinary *binary) { aclDevCaps *caps = NULL; if (binary->struct_size == sizeof(aclBinary_0_8)) { caps = &reinterpret_cast(binary)->caps; } else if (binary->struct_size == sizeof(aclBinary_0_8_1)) { caps = &reinterpret_cast(binary)->caps; } else { assert(!"Binary format not supported!"); caps = &binary->caps; } return caps; } // Helper function that returns the // allocation function from the binary. AllocFunc aclutAlloc(const aclBinary *bin) { size_t size = (bin ? bin->struct_size : 0); AllocFunc m = NULL; switch(size) { case 0: case sizeof(aclBinary_0_8): break; case sizeof(aclBinary_0_8_1): m = reinterpret_cast(bin)->binOpts.alloc; break; default: assert(!"Found an unsupported binary!"); m = bin->binOpts.alloc; break; } return (m) ? m : &::malloc; } // Helper function that returns the // allocation function from the compiler. AllocFunc aclutAlloc(const aclCompiler *bin) { size_t size = (bin ? bin->struct_size : 0); AllocFunc m = NULL; switch(size) { case 0: case sizeof(aclCompilerHandle_0_8): break; case sizeof(aclCompilerHandle_0_8_1): m = reinterpret_cast(bin)->alloc; break; default: assert(!"Found an unsupported compiler!"); m = bin->alloc; break; } return (m) ? m : &::malloc; } AllocFunc aclutAlloc(const aclCompilerOptions *opts) { size_t size = (opts ? opts->struct_size : 0); AllocFunc m = NULL; switch (size) { case 0: case sizeof(aclCompilerOptions_0_8): break; case sizeof(aclCompilerOptions_0_8_1): m = reinterpret_cast(opts)->alloc; break; default: assert(!"Found an unsupported compiler options struct!"); m = opts->alloc; break; } return (m) ? m : &::malloc; } // Helper function that returns the // de-allocation function from the compiler. FreeFunc aclutFree(const aclCompiler *bin) { size_t size = (bin ? bin->struct_size : 0); FreeFunc f = NULL; switch(size) { case 0: case sizeof(aclCompilerHandle_0_8): break; case sizeof(aclCompilerHandle_0_8_1): f = reinterpret_cast(bin)->dealloc; break; default: assert(!"Found an unsupported compiler!"); f = bin->dealloc; break; } return (f) ? f : &::free; } // Helper function that returns the // de-allocation function from the binary. FreeFunc aclutFree(const aclBinary *bin) { size_t size = (bin ? bin->struct_size : 0); FreeFunc f = NULL; switch(size) { case 0: case sizeof(aclBinary_0_8): break; case sizeof(aclBinary_0_8_1): f = reinterpret_cast(bin)->binOpts.dealloc; break; default: assert(!"Found an unsupported binary!"); f = bin->binOpts.dealloc; break; } return (f) ? f : &::free; } FreeFunc aclutFree(const aclCompilerOptions *opts) { size_t size = (opts ? opts->struct_size : 0); FreeFunc f = NULL; switch (size) { case 0: case sizeof(aclCompilerOptions_0_8): break; case sizeof(aclCompilerOptions_0_8_1): f = reinterpret_cast(opts)->dealloc; break; default: assert(!"Found an unsupported compiler options struct!"); f = opts->dealloc; break; } return (f) ? f : &::free; } void aclutCopyBinOpts(aclBinaryOptions *dst, const aclBinaryOptions *src, bool is64) { if (dst == src) return; aclBinaryOptions_0_8 *dst08; aclBinaryOptions_0_8_1 *dst081; const aclBinaryOptions_0_8 *src08; const aclBinaryOptions_0_8_1 *src081; dst08 = reinterpret_cast(dst); dst081 = reinterpret_cast(dst); src08 = reinterpret_cast(src); src081 = reinterpret_cast(src); unsigned size = (src ? src->struct_size : 0); switch (size) { case 0: switch (dst->struct_size) { case sizeof(aclBinary_0_8): dst08->elfclass = (is64) ? ELFCLASS64 : ELFCLASS32; dst08->bitness = ELFDATA2LSB; dst08->temp_file = ""; dst08->kernelArgAlign = 4; break; case sizeof(aclBinary_0_8_1): dst081->elfclass = (is64) ? ELFCLASS64 : ELFCLASS32; dst081->bitness = ELFDATA2LSB; dst081->temp_file = ""; dst081->kernelArgAlign = 4; dst081->alloc = &::malloc; dst081->dealloc = &::free; break; default: dst->elfclass = (is64) ? ELFCLASS64 : ELFCLASS32; dst->bitness = ELFDATA2LSB; dst->temp_file = ""; dst->kernelArgAlign = 4; dst->alloc = &::malloc; dst->dealloc = &::free; break; } break; case sizeof(aclBinaryOptions_0_8): switch (dst->struct_size) { case sizeof(aclBinaryOptions_0_8): memcpy(dst08, src08, src08->struct_size); break; case sizeof(aclBinaryOptions_0_8_1): dst081->elfclass = src08->elfclass; dst081->bitness = src08->bitness; dst081->temp_file = src08->temp_file; dst081->kernelArgAlign = src08->kernelArgAlign; dst081->alloc = &::malloc; dst081->dealloc = &::free; break; default: assert(!"aclBinary format is not supported!"); memcpy(dst, src08, src08->struct_size); if (!dst->alloc) dst->alloc = &::malloc; if (!dst->dealloc) dst->dealloc = &::free; } break; case sizeof(aclBinaryOptions_0_8_1): switch (dst->struct_size) { case sizeof(aclBinary_0_8): dst08->elfclass = src081->elfclass; dst08->bitness = src081->bitness; dst08->temp_file = src081->temp_file; dst08->kernelArgAlign = src081->kernelArgAlign; break; case sizeof(aclBinaryOptions_0_8_1): memcpy(dst081, src081, src081->struct_size); if (!dst->alloc) dst->alloc = &::malloc; if (!dst->dealloc) dst->dealloc = &::free; break; default: assert(!"aclBinary format is not supported!"); memcpy(dst, src081, src081->struct_size); if (!dst->alloc) dst->alloc = &::malloc; if (!dst->dealloc) dst->dealloc = &::free; } break; default: assert(!"aclBinary format is not supported!"); memcpy(dst, src, src->struct_size); } } acl_error aclutInsertKernelStatistics(aclCompiler *cl, aclBinary *bin) { if (!aclValidateCompiler(cl, true)) { return ACL_INVALID_COMPILER; } if (!aclValidateBinary(bin)) { return ACL_INVALID_BINARY; } size_t len = 0; acl_error err = ACL_SUCCESS; const void *isa = aclExtractSection(cl, bin, &len, aclTEXT, &err); if (err != ACL_SUCCESS) return err; aclTargetInfo *tgtInfo = aclutGetTargetInfo(bin); const char* chipName = aclGetChip(*tgtInfo); unsigned family = getFamilyEnum(tgtInfo); unsigned chip = getChipEnum(tgtInfo); // Non-GPU devices have family_enum set to 1 and do not qualify. Need to update. if (family >= FAMILY_R600 && family <= FAMILY_CZ) { aclKernelStats kstats = {0}; aclGetKstatsSI(isa, kstats); kstats.wavefrontsize = 64; // FIXME: Hardcoded for now. const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symKernelStats); assert(symbol && "symbol not found"); std::string symName = std::string(symbol->str[PRE]) + std::string(symbol->str[POST]); err = aclInsertSymbol(cl, bin, reinterpret_cast(&kstats), sizeof(kstats), aclKSTATS, symName.c_str()); } return err; } std::string aclutGetCodegenName(const aclTargetInfo &tgtInfo) { assert(tgtInfo.arch_id <= aclLast && "Unknown device id!"); const FamilyMapping *family = familySet + tgtInfo.arch_id; if (!family) return ""; assert((tgtInfo.chip_id) < family->children_size && "Unknown family id!"); const TargetMapping *target = &family->target[tgtInfo.chip_id]; return (target) ? target->codegen_name : ""; } void initElfDeviceCaps(aclBinary *elf) { if (aclutGetCaps(elf)->encryptCode) { setEncryptCaps(aclutGetCaps(elf)); return; } if (aclutGetOptions(elf)) { setOptionCaps(reinterpret_cast( aclutGetOptions(elf)), aclutGetCaps(elf)); } } const char *getDeviceName(const aclTargetInfo &target) { if (target.chip_id) { return aclGetChip(target); } else if (target.arch_id) { return aclGetArchitecture(target); } return NULL; } const TargetMapping& getTargetMapping(const aclTargetInfo &target) { switch (target.arch_id) { default: break; case aclX64: return X64TargetMapping[target.chip_id]; break; case aclX86: return X86TargetMapping[target.chip_id]; break; case aclHSAIL: return HSAILTargetMapping[target.chip_id]; break; case aclHSAIL64: return HSAIL64TargetMapping[target.chip_id]; break; case aclAMDIL: return AMDILTargetMapping[target.chip_id]; break; case aclAMDIL64: return AMDIL64TargetMapping[target.chip_id]; break; }; return UnknownTarget; } bool isChipSupported(const aclTargetInfo& target) { if (!isValidTarget(target)) { return false; } const TargetMapping& Mapping = getTargetMapping(target); if (Mapping.family_enum == FAMILY_UNKNOWN) { return false; } return Mapping.supported; } /*! Function that returns the library type from the TargetMapping table for *the specific target device id. */ amd::LibrarySelector getLibraryType(const aclTargetInfo *target) { const TargetMapping& Mapping = getTargetMapping(*target); return Mapping.lib; } /*! Function that returns family_enum from the TargetMapping table for *the specific target device id. */ unsigned getFamilyEnum(const aclTargetInfo *target) { const TargetMapping& Mapping = getTargetMapping(*target); return Mapping.family_enum; } /*! Function that returns chip_enum from the TargetMapping table for *the specific target device id. */ unsigned getChipEnum(const aclTargetInfo *target) { const TargetMapping& Mapping = getTargetMapping(*target); return Mapping.chip_enum; } /*! Function that returns isa type name (compute capability) from *the TargetMapping table for the specific target device id. */ const std::string &getIsaTypeName(const aclTargetInfo *target) { switch (getIsaType(target)) { default: return sgfx700; case 700: return sgfx700; case 701: return sgfx701; case 800: return sgfx800; case 801: return sgfx801; case 802: return sgfx802; case 803: return sgfx803; case 804: return sgfx804; case 810: return sgfx810; case 900: return sgfx900; case 901: return sgfx901; case 902: return sgfx902; case 903: return sgfx903; case 904: return sgfx904; case 905: return sgfx905; case 906: return sgfx906; case 907: return sgfx907; case 908: return sgfx908; case 1000: return sgfx1000; case 1010: return sgfx1010; case 1011: return sgfx1011; case 1012: return sgfx1012; } } /*! Function that returns isa type (compute capability) from *the TargetMapping table for the specific target device id. */ int getIsaType(const aclTargetInfo *target) { const TargetMapping& Mapping = getTargetMapping(*target); switch (Mapping.family_enum) { default: return 700; case FAMILY_KV: switch (Mapping.chip_enum) { default: return 700; case KV_SPECTRE_A0: case KV_SPOOKY_A0: case KB_KALINDI_A0: // ??? case ML_GODAVARI_A0: return 700; } case FAMILY_CI: switch (Mapping.chip_enum) { default: return 700; case CI_BONAIRE_M_A0: case CI_BONAIRE_M_A1: return 700; case CI_HAWAII_P_A0: return 701; case CI_TIRAN_P_A0: case CI_MAUI_P_A0: return 700; } case FAMILY_VI: switch (Mapping.chip_enum) { default: return 800; case VI_TONGA_P_A0: #if defined(BUILD_HSA_TARGET) return 802; // Special case - Boltzmann Tonga // Otherwise fall through #endif case VI_ICELAND_M_A0: return 800; case VI_FIJI_P_A0: case VI_BAFFIN_M_A0: case VI_BAFFIN_M_A1: case VI_ELLESMERE_P_A0: case VI_ELLESMERE_P_A1: case VI_LEXA_V_A0: case VI_POLARIS22_P_A0: #if defined(BUILD_HSA_TARGET) return 803; // Special case - Boltzmann FIJI, BAFFIN, ELLESMERE, LEXA // Otherwise fall through #else return 804; #endif } case FAMILY_CZ: switch (Mapping.chip_enum) { default: return 801; case CARRIZO_A0: return 801; case STONEY_A0: return 810; } case FAMILY_AI: switch (Mapping.chip_enum) { default: return 900; case AI_GREENLAND_P_A0: case AI_GREENLAND_P_A1: return Mapping.xnack_supported ? 901 : 900; case AI_VEGA12_P_A0: return Mapping.xnack_supported ? 905 : 904; case AI_VEGA20_P_A0: return Mapping.xnack_supported ? 907 : 906; case AI_MI100_P_A0: return 908; } case FAMILY_RV: switch (Mapping.chip_enum) { default: return 902; case RAVEN_A0: case RENOIR_A0: return Mapping.xnack_supported ? 903 : 902; } case FAMILY_NV: switch (Mapping.chip_enum) { default: return 1000; case NV_NAVI10_LITE_P_A0: return 1000; case NV_NAVI10_P_A0: return 1010; case NV_NAVI12_P_A0: return 1011; case NV_NAVI14_M_A0: return 1012; } } } std::string getFeatureString(const aclTargetInfo& target, amd::option::Options *OptionsObj) { std::string FeatureStr; if (isHSAILTarget(target)) { uint64_t y = aclGetChipOptions(target); FeatureStr += ((y & F_FP32_DENORMS) && !OptionsObj->oVariables->DenormsAreZero) ? '+' : '-'; FeatureStr += "fp32-denormals"; for (uint64_t x = 0; y != 0; y >>= 1, ++x) { if ((1 << x) == F_FP32_DENORMS) { continue; } if (!FeatureStr.empty()) { FeatureStr += ','; } FeatureStr += ((y & 0x1) ? '+' : '-'); FeatureStr += HSAILCodeGenFlagTable[x]; } } return FeatureStr; } void appendLogToCL(aclCompiler *cl, const std::string &logStr) { if (logStr.empty()) { return; } std::string log = logStr; if ('\n' != log[log.size()-1]) { log.append("\n"); } unsigned size = cl->logSize + log.size(); if (!size) { return; } char *tmpBuildLog = reinterpret_cast(aclutAlloc(cl)(size + 2)); memset(tmpBuildLog, 0, size + 2); if (cl->logSize) { std::copy(cl->buildLog, cl->buildLog + cl->logSize, tmpBuildLog); std::copy(log.begin(), log.end(), tmpBuildLog + cl->logSize); } else { std::copy(log.begin(), log.end(), tmpBuildLog); } cl->logSize += (unsigned int)log.size(); if (cl->buildLog) { aclutFree(cl)(cl->buildLog); } cl->buildLog = tmpBuildLog; } static void setElfTarget(bifbase *elfBin, const aclTargetInfo *tgtInfo) { uint16_t elf_target = 0; switch (tgtInfo->arch_id) { default: assert(!"creating an elf for an invalid architecture!"); case aclX86: elfBin->setTarget(EM_386, aclPlatformCompLib); break; case aclX64: elfBin->setTarget(EM_X86_64, aclPlatformCompLib); break; case aclHSAIL: elfBin->setTarget(EM_HSAIL, aclPlatformCompLib); break; case aclHSAIL64: elfBin->setTarget(EM_HSAIL_64, aclPlatformCompLib); break; case aclAMDIL: elfBin->setTarget(EM_AMDIL, aclPlatformCompLib); break; case aclAMDIL64: elfBin->setTarget(EM_AMDIL_64, aclPlatformCompLib); break; } } // FIXME: this needs to be moved into the BIF classes. static void convertBIF30MachineTo2X(bifbase *elfBin, const aclTargetInfo *tgtInfo) { uint16_t machine = 0; uint32_t flags = 0; aclPlatform pform = aclPlatformLast; if (elfBin == NULL) return; elfBin->getTarget(machine, pform); assert(pform == aclPlatformCompLib && "Platform is specified incorrectly!"); if (isCpuTarget(*tgtInfo)) { assert(!"Not implemented/supported family detected!"); pform = aclPlatformCPU; } else if (isAMDILTarget(*tgtInfo)) { const char* chip = aclGetChip(*tgtInfo); for (unsigned x = 0, y = sizeof(calTargetMapping)/sizeof(calTargetMapping[0]); x < y; ++x) { if (!strcmp(chip, calTargetMapping[x])) { machine = x; break; } } pform = aclPlatformCAL; } else { assert(!"Not implemented/supported family detected!"); } elfBin->setTarget(machine, pform); } // FIXME: This needs to be moved into the elf classes static void convertBIF2XMachineTo31(bifbase *elfBin) { uint16_t machine = 0; aclPlatform pform = aclPlatformLast; if (elfBin == NULL) return; elfBin->getTarget(machine, pform); assert(pform != aclPlatformCompLib && "Platform is specified incorrectly!"); if (pform == aclPlatformCPU) { uint16_t type; elfBin->getType(type); machine = (type == ELFCLASS32 ? EM_386 : EM_X86_64); } else if (pform == aclPlatformCAL) { machine = EM_AMDIL; } else { assert(!"Unknown platform found!"); } pform = aclPlatformCompLib; elfBin->setTarget(machine, pform); } static void convertBIF2XMachineTo30(bifbase *elfBin) { uint16_t machine = 0; aclPlatform pform = aclPlatformLast; if (elfBin == NULL) return; elfBin->getTarget(machine, pform); assert(pform != aclPlatformCompLib && "Platform is specified incorrectly!"); if (pform == aclPlatformCPU) { uint16_t type; elfBin->getType(type); machine = (type == ELFCLASS32 ? EM_386 : EM_X86_64); } else if (pform == aclPlatformCAL) { machine = EM_AMDIL; } else { assert(!"Unknown platform found!"); } pform = aclPlatformCompLib; elfBin->setTarget(machine, pform); } static void setElfFlags(bifbase *elfBin, const aclTargetInfo *tgtInfo) { uint32_t flags = 0; elfBin->getFlags(flags); flags &= 0xFFFF0000; const FamilyMapping *family = familySet + tgtInfo->arch_id; flags = tgtInfo->chip_id & 0xFFFF; elfBin->setFlags(flags); } static aclBinary* cloneOclElfNoBIF(const aclBinary *src) { if (src == NULL) return NULL; if (src->struct_size == sizeof(aclBinary_0_8_1)) { aclBinary *dst = constructBinary(src->struct_size, aclutGetTargetInfo(const_cast(src)), aclutGetBinOpts(const_cast(src))); if (dst == NULL) { return NULL; } aclBinary_0_8_1 *dptr = reinterpret_cast(dst); const aclBinary_0_8_1 *sptr = reinterpret_cast(src); dptr->target.struct_size = sizeof(aclTargetInfo_0_8); if (sptr->target.struct_size == sizeof(aclTargetInfo_0_8)) { memcpy(&dptr->target, &sptr->target, sptr->target.struct_size); } else { assert(!"Unsupported target info detected!"); } memcpy(&dptr->caps, &sptr->caps, sptr->caps.struct_size); assert(sizeof(aclDevCaps_0_8) == dptr->caps.struct_size); amd::option::Options *Opts = reinterpret_cast( aclutAlloc(src)(sizeof(amd::option::Options))); Opts = new (Opts) amd::option::Options; amd::option::Options *sOpts = reinterpret_cast( sptr->options); if (sOpts) { parseAllOptions(sOpts->origOptionStr, *Opts, false, false); } dptr->options = reinterpret_cast(Opts); dptr->bin = NULL; return dst; } else if (src->struct_size == sizeof(aclBinary_0_8)) { aclBinary *dst = constructBinary(src->struct_size, &src->target, &src->binOpts); if (dst == NULL) { return NULL; } aclBinary_0_8 *dptr = reinterpret_cast(dst); const aclBinary_0_8 *sptr = reinterpret_cast(src); dptr->target.struct_size = sizeof(aclTargetInfo_0_8); if (sptr->target.struct_size == sizeof(aclTargetInfo_0_8)) { memcpy(&dptr->target, &sptr->target, sptr->target.struct_size); } else { assert(!"Unsupported target info detected!"); } memcpy(&dptr->caps, &sptr->caps, sptr->caps.struct_size); assert(sizeof(aclDevCaps_0_8) == dptr->caps.struct_size && "The caps struct is not version 0.7!"); amd::option::Options *Opts = reinterpret_cast( aclutAlloc(src)(sizeof(amd::option::Options))); Opts = new (Opts) amd::option::Options; amd::option::Options *sOpts = reinterpret_cast( sptr->options); if (sOpts) { parseAllOptions(sOpts->origOptionStr, *Opts, false, false); } dptr->options = reinterpret_cast(Opts); dptr->bin = NULL; return dst; } else { assert(!"Elf version not supported!"); } return NULL; } // Create a copy of an ELF and duplicate all sections/symbols // All sections are copied verbatim. aclBinary* createELFCopy(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); bifbase* dstBin = NULL; switch (srcBin->getVersion()) { default: assert(!"New/unknown version detected!"); dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bifbase))); dstBin = new (dstBin) bifbase(srcBin->getBase()); break; case aclBIFVersion20: dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif20))); dstBin = new (dstBin) bif20(srcBin->get20()); break; case aclBIFVersion21: dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif21))); dstBin = new (dstBin) bif21(srcBin->get21()); break; case aclBIFVersion30: dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif30))); dstBin = new (dstBin) bif30(srcBin->get30()); break; case aclBIFVersion31: dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif31))); dstBin = new (dstBin) bif31(srcBin->get31()); break; } if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF2.1 elf from a BIF 2.0 elf. // All sections are copied and then if // CAL/DLL or JITBINARY sections are found, // the type is set to EXEC. aclBinary* convertBIF20ToBIF21(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get20() != NULL && "Passed in an invalid binary!"); bif21 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif21))); dstBin = new (dstBin) bif21(srcBin->get20()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF3.0 elf from a BIF 2.0 elf. aclBinary* convertBIF20ToBIF30(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get20() != NULL && "Passed in an invalid binary!"); bif30 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif30))); dstBin = new (dstBin) bif30(srcBin->get20()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); convertBIF2XMachineTo30(dstBin); } return dst; } // Create a BIF3.1 elf from a BIF 2.0 elf. aclBinary* convertBIF20ToBIF31(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get20() != NULL && "Passed in an invalid binary!"); bif31 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif31))); dstBin = new (dstBin) bif31(srcBin->get20()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); convertBIF2XMachineTo31(dstBin); } return dst; } // Create a BIF2.0 elf from a BIF 2.1 elf. // All sections except for the COMMENT section is copied // verbatim and the section is set to NONE. aclBinary* convertBIF21ToBIF20(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get21() != NULL && "Passed in an invalid binary!"); bif20 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif20))); dstBin = new (dstBin) bif20(srcBin->get21()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF3.0 elf from a BIF 2.1 elf. // See BIF spec for 2.1 to 3.0 conversion // and also include the comment section. aclBinary* convertBIF21ToBIF30(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get21() != NULL && "Passed in an invalid binary!"); bif30 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif30))); dstBin = new (dstBin) bif30(srcBin->get21()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); convertBIF2XMachineTo30(dstBin); } return dst; } // Create a BIF3.1 elf from a BIF 2.1 elf. // See BIF spec for 3.1 to 2.1 conversion. aclBinary* convertBIF21ToBIF31(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get21() != NULL && "Passed in an invalid binary!"); bif31 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif31))); dstBin = new (dstBin) bif31(srcBin->get21()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); convertBIF2XMachineTo31(dstBin); } return dst; } // Create a BIF2.0 elf from a BIF 3.0 elf. // See BIF spec for 3.0 to 2.0 conversion. aclBinary* convertBIF30ToBIF20(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get30() != NULL && "Passed in an invalid binary!"); bif20 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif20))); dstBin = new (dstBin) bif20(srcBin->get30()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF2.1 elf from a BIF 3.0 elf // See BIF spec for 3.0 to 2.1 conversion // but also include the COMMENT section. aclBinary* convertBIF30ToBIF21(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get30() != NULL && "Passed in an invalid binary!"); bif21 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif21))); dstBin = new (dstBin) bif21(srcBin->get30()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF3.1 elf from a BIF 3.0 elf // See BIF spec for 3.0 to 3.1 conversion. aclBinary* convertBIF30ToBIF31(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get30() != NULL && "Passed in an invalid binary!"); bif31 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif31))); dstBin = new (dstBin) bif31(srcBin->get30()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF2.0 elf from a BIF 3.1 elf. // See BIF spec for 3.1 to 2.0 conversion. aclBinary* convertBIF31ToBIF20(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get31() != NULL && "Passed in an invalid binary!"); bif20 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif20))); dstBin = new (dstBin) bif20(srcBin->get31()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF2.1 elf from a BIF 3.1 elf // See BIF spec for 3.1 to 2.1 conversion. aclBinary* convertBIF31ToBIF21(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get31() != NULL && "Passed in an invalid binary!"); bif21 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif21))); dstBin = new (dstBin) bif21(srcBin->get31()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } // Create a BIF3.1 elf from a BIF 3.0 elf // See BIF spec for 3.0 to 3.1 conversion. aclBinary* convertBIF31ToBIF30(aclBinary *src) { aclBinary *dst = cloneOclElfNoBIF(src); if (dst != NULL) { bifbase *srcBin = reinterpret_cast(aclutGetBIF(src)); assert(srcBin->get31() != NULL && "Passed in an invalid binary!"); bif30 *dstBin = NULL; dstBin = reinterpret_cast(aclutAlloc(src)(sizeof(bif30))); dstBin = new (dstBin) bif30(srcBin->get31()); if (dstBin->hasError()) { aclBinaryFini(dst); return NULL; } dst->bin = reinterpret_cast(dstBin); } return dst; } void dump(aclBinary *bin) { bifbase *elfBin = reinterpret_cast(bin->bin); elfBin->dump(); } const std::string &getLegacyLibName() { return legacyLibName; }