/* * Copyright (C) 2017-2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/built_ins/sip.h" #include "shared/source/compiler_interface/compiler_cache.h" #include "shared/source/helpers/string.h" #include "shared/source/os_interface/os_library.h" #include "shared/source/utilities/arrayref.h" #include "shared/source/utilities/spinlock.h" #include "cif/common/cif_main.h" #include "ocl_igc_interface/code_type.h" #include "ocl_igc_interface/fcl_ocl_device_ctx.h" #include "ocl_igc_interface/igc_ocl_device_ctx.h" #include #include namespace NEO { class Device; using specConstValuesMap = std::unordered_map; struct TranslationInput { TranslationInput(IGC::CodeType::CodeType_t srcType, IGC::CodeType::CodeType_t outType, IGC::CodeType::CodeType_t preferredIntermediateType = IGC::CodeType::undefined) : srcType(srcType), preferredIntermediateType(preferredIntermediateType), outType(outType) { } bool allowCaching = false; ArrayRef src; ArrayRef apiOptions; ArrayRef internalOptions; const char *tracingOptions = nullptr; uint32_t tracingOptionsCount = 0; IGC::CodeType::CodeType_t srcType = IGC::CodeType::invalid; IGC::CodeType::CodeType_t preferredIntermediateType = IGC::CodeType::invalid; IGC::CodeType::CodeType_t outType = IGC::CodeType::invalid; void *GTPinInput = nullptr; specConstValuesMap specializedValues; }; struct TranslationOutput { enum class ErrorCode { Success = 0, CompilerNotAvailable, CompilationFailure, BuildFailure, LinkFailure, AlreadyCompiled, UnknownError, }; struct MemAndSize { std::unique_ptr mem; size_t size = 0; }; IGC::CodeType::CodeType_t intermediateCodeType = IGC::CodeType::invalid; MemAndSize intermediateRepresentation; MemAndSize deviceBinary; MemAndSize debugData; std::string frontendCompilerLog; std::string backendCompilerLog; template static void makeCopy(ContainerT &dst, CIF::Builtins::BufferSimple *src) { if ((nullptr == src) || (src->GetSizeRaw() == 0)) { dst.clear(); return; } dst.assign(src->GetMemory(), src->GetSize()); } static void makeCopy(MemAndSize &dst, CIF::Builtins::BufferSimple *src) { if ((nullptr == src) || (src->GetSizeRaw() == 0)) { dst.mem.reset(); dst.size = 0U; return; } dst.size = src->GetSize(); dst.mem = ::makeCopy(src->GetMemory(), src->GetSize()); } }; struct SpecConstantInfo { CIF::RAII::UPtr_t idsBuffer; CIF::RAII::UPtr_t sizesBuffer; }; class CompilerInterface { public: CompilerInterface(); CompilerInterface(const CompilerInterface &) = delete; CompilerInterface &operator=(const CompilerInterface &) = delete; CompilerInterface(CompilerInterface &&) = delete; CompilerInterface &operator=(CompilerInterface &&) = delete; virtual ~CompilerInterface(); template static CompilerInterfaceT *createInstance(std::unique_ptr cache, bool requireFcl) { auto instance = new CompilerInterfaceT(); if (!instance->initialize(std::move(cache), requireFcl)) { delete instance; instance = nullptr; } return instance; } MOCKABLE_VIRTUAL TranslationOutput::ErrorCode build(const NEO::Device &device, const TranslationInput &input, TranslationOutput &output); MOCKABLE_VIRTUAL TranslationOutput::ErrorCode compile(const NEO::Device &device, const TranslationInput &input, TranslationOutput &output); MOCKABLE_VIRTUAL TranslationOutput::ErrorCode link(const NEO::Device &device, const TranslationInput &input, TranslationOutput &output); MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSpecConstantsInfo(const NEO::Device &device, ArrayRef srcSpirV, SpecConstantInfo &output); TranslationOutput::ErrorCode createLibrary(NEO::Device &device, const TranslationInput &input, TranslationOutput &output); MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSipKernelBinary(NEO::Device &device, SipKernelType type, std::vector &retBinary); protected: MOCKABLE_VIRTUAL bool initialize(std::unique_ptr cache, bool requireFcl); MOCKABLE_VIRTUAL bool loadFcl(); MOCKABLE_VIRTUAL bool loadIgc(); static SpinLock spinlock; MOCKABLE_VIRTUAL std::unique_lock lock() { return std::unique_lock{spinlock}; } std::unique_ptr cache = nullptr; using igcDevCtxUptr = CIF::RAII::UPtr_t; using fclDevCtxUptr = CIF::RAII::UPtr_t; std::unique_ptr igcLib; CIF::RAII::UPtr_t igcMain = nullptr; std::map igcDeviceContexts; std::unique_ptr fclLib; CIF::RAII::UPtr_t fclMain = nullptr; std::map fclDeviceContexts; CIF::RAII::UPtr_t fclBaseTranslationCtx = nullptr; MOCKABLE_VIRTUAL IGC::FclOclDeviceCtxTagOCL *getFclDeviceCtx(const Device &device); MOCKABLE_VIRTUAL IGC::IgcOclDeviceCtxTagOCL *getIgcDeviceCtx(const Device &device); MOCKABLE_VIRTUAL IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation(const Device &device); MOCKABLE_VIRTUAL CIF::RAII::UPtr_t createFclTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType); MOCKABLE_VIRTUAL CIF::RAII::UPtr_t createIgcTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType); bool isFclAvailable() const { return (fclMain != nullptr); } bool isIgcAvailable() const { return (igcMain != nullptr); } bool isCompilerAvailable(IGC::CodeType::CodeType_t translationSrc, IGC::CodeType::CodeType_t translationDst) const { bool requiresFcl = (IGC::CodeType::oclC == translationSrc); bool requiresIgc = (IGC::CodeType::oclC != translationSrc) || ((IGC::CodeType::spirV != translationDst) && (IGC::CodeType::llvmBc != translationDst) && (IGC::CodeType::llvmLl != translationDst)); return (isFclAvailable() || (false == requiresFcl)) && (isIgcAvailable() || (false == requiresIgc)); } }; } // namespace NEO