diff --git a/sycl/plugins/level_zero/pi_level_zero.cpp b/sycl/plugins/level_zero/pi_level_zero.cpp index 1bf28dd1bb3b2..b57716b95d2fc 100644 --- a/sycl/plugins/level_zero/pi_level_zero.cpp +++ b/sycl/plugins/level_zero/pi_level_zero.cpp @@ -3785,8 +3785,6 @@ pi_result piProgramLink(pi_context Context, pi_uint32 NumDevices, const pi_program *InputPrograms, void (*PFnNotify)(pi_program Program, void *UserData), void *UserData, pi_program *RetProgram) { - (void)Options; - // We only support one device with Level Zero currently. pi_device Device = Context->Devices[0]; if (NumDevices != 1) { @@ -3794,6 +3792,19 @@ pi_result piProgramLink(pi_context Context, pi_uint32 NumDevices, return PI_INVALID_VALUE; } + // We do not support any link flags at this time because the Level Zero API + // does not have any way to pass flags that are specific to linking. + if (Options && *Options != '\0') { + std::string ErrorMessage( + "Level Zero does not support kernel link flags: \""); + ErrorMessage.append(Options); + ErrorMessage.push_back('\"'); + pi_program Program = + new _pi_program(_pi_program::Invalid, Context, ErrorMessage); + *RetProgram = Program; + return PI_LINK_PROGRAM_FAILURE; + } + // Validate input parameters. PI_ASSERT(DeviceList && DeviceList[0] == Device, PI_INVALID_DEVICE); PI_ASSERT(!PFnNotify && !UserData, PI_INVALID_VALUE); @@ -4051,16 +4062,26 @@ pi_result piProgramGetBuildInfo(pi_program Program, pi_device Device, // with piProgramRegister? return ReturnValue(""); } else if (ParamName == CL_PROGRAM_BUILD_LOG) { - // The OpenCL spec says an empty string is returned if there was no - // previous Compile, Build, or Link. - if (!Program->ZeBuildLog) - return ReturnValue(""); - size_t LogSize = ParamValueSize; - ZE_CALL(zeModuleBuildLogGetString, - (Program->ZeBuildLog, &LogSize, pi_cast(ParamValue))); - if (ParamValueSizeRet) { - *ParamValueSizeRet = LogSize; + // Check first to see if the plugin code recorded an error message. + if (!Program->ErrorMessage.empty()) { + return ReturnValue(Program->ErrorMessage.c_str()); } + + // Next check if there is a Level Zero build log. + if (Program->ZeBuildLog) { + size_t LogSize = ParamValueSize; + ZE_CALL(zeModuleBuildLogGetString, + (Program->ZeBuildLog, &LogSize, pi_cast(ParamValue))); + if (ParamValueSizeRet) { + *ParamValueSizeRet = LogSize; + } + return PI_SUCCESS; + } + + // Otherwise, there is no error. The OpenCL spec says to return an empty + // string if there ws no previous attempt to compile, build, or link the + // program. + return ReturnValue(""); } else { zePrint("piProgramGetBuildInfo: unsupported ParamName\n"); return PI_INVALID_VALUE; diff --git a/sycl/plugins/level_zero/pi_level_zero.hpp b/sycl/plugins/level_zero/pi_level_zero.hpp index a40ae9b46fcae..ec5f4c3fdafdb 100644 --- a/sycl/plugins/level_zero/pi_level_zero.hpp +++ b/sycl/plugins/level_zero/pi_level_zero.hpp @@ -1075,6 +1075,11 @@ struct _pi_program : _pi_object { : Context{Context}, OwnZeModule{OwnZeModule}, State{St}, ZeModule{ZeModule}, ZeBuildLog{nullptr} {} + // Construct a program in Invalid state with a custom error message. + _pi_program(state St, pi_context Context, const std::string &ErrorMessage) + : Context{Context}, OwnZeModule{true}, ErrorMessage{ErrorMessage}, + State{St}, ZeModule{nullptr}, ZeBuildLog{nullptr} {} + ~_pi_program(); const pi_context Context; // Context of the program. @@ -1083,6 +1088,10 @@ struct _pi_program : _pi_object { // asked to not transfer the ownership to SYCL RT. const bool OwnZeModule; + // This error message is used only in Invalid state to hold a custom error + // message from a call to piProgramLink. + const std::string ErrorMessage; + // Protects accesses to all the non-const member variables. Exclusive access // is required to modify any of these members. std::shared_mutex Mutex;