blob: 7199e3a3f10f032f12a6dff60bc0fe609aa1e453 [file]
//===-- LanguageLaunch.cpp - Language launch API --------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "LanguageLaunch.h"
#include "LanguageUtils.h"
#include "State.h"
#include <cstdio>
using RuntimeState = llvm::offload::StateTy;
using ThreadState = llvm::offload::ThreadStateTy;
static constexpr ol_error_struct_t InvalidKernelError = {
OL_ERRC_INVALID_NULL_HANDLE, "kernel is not registered"};
static constexpr ol_error_struct_t InvalidDeviceError = {OL_ERRC_INVALID_DEVICE,
"invalid device"};
static constexpr ol_error_struct_t InvalidArgumentError = {
OL_ERRC_INVALID_ARGUMENT, "invalid argument to kernel launch"};
static constexpr ol_error_struct_t InvalidConfigurationError = {
OL_ERRC_INVALID_SIZE, "invalid kernel launch configuration"};
/// Internal kernel launch implementation
ol_result_t __llvmLaunchKernelImpl(const char *KernelID, dim3 GridDim,
dim3 BlockDim, void *KernelArgsPtr,
size_t DynamicSharedMem, void *Stream) {
ol_device_handle_t Device = ThreadState::getDefaultDevice();
ol_symbol_handle_t Kernel = RuntimeState::getKernel(KernelID);
if (!Device)
return &InvalidDeviceError;
if (!KernelID || !KernelArgsPtr)
return &InvalidArgumentError;
if (!Kernel)
return &InvalidKernelError;
if (GridDim.x == 0 || GridDim.y == 0 || GridDim.z == 0 || BlockDim.x == 0 ||
BlockDim.y == 0 || BlockDim.z == 0)
return &InvalidConfigurationError;
ol_kernel_launch_size_args_t LaunchSizeArgs;
LaunchSizeArgs.Dimensions =
1 + (GridDim.y > 1 || BlockDim.y > 1) + (GridDim.z > 1 || BlockDim.z > 1);
LaunchSizeArgs.NumGroups.x = GridDim.x;
LaunchSizeArgs.NumGroups.y = GridDim.y;
LaunchSizeArgs.NumGroups.z = GridDim.z;
LaunchSizeArgs.GroupSize.x = BlockDim.x;
LaunchSizeArgs.GroupSize.y = BlockDim.y;
LaunchSizeArgs.GroupSize.z = BlockDim.z;
LaunchSizeArgs.DynSharedMemory = DynamicSharedMem;
ol_queue_handle_t Queue = Stream ? reinterpret_cast<ol_queue_handle_t>(Stream)
: ThreadState::getDefaultQueue();
struct OffloadKernelArgs {
void **Args;
size_t NumArgs;
size_t *ArgSizes;
};
OffloadKernelArgs *OKA = static_cast<OffloadKernelArgs *>(KernelArgsPtr);
if ((!OKA->Args) != (!OKA->ArgSizes))
return &InvalidArgumentError;
if (OKA->NumArgs > 0 && !OKA->Args)
return &InvalidArgumentError;
for (size_t I = 0; I < OKA->NumArgs; ++I)
if (!OKA->Args[I] || OKA->ArgSizes[I] == 0)
return &InvalidArgumentError;
return olLaunchKernel(Queue, Device, Kernel, &LaunchSizeArgs,
/*Properties=*/nullptr, OKA->NumArgs, OKA->Args,
OKA->ArgSizes);
}
extern "C" {
/// Push call configuration for kernel launch
unsigned __llvmPushCallConfiguration(dim3 GridSize, dim3 BlockSize,
size_t SharedMemory, void *Stream) {
CallConfigurationTy &CC = ThreadState::getCallConfiguration();
CC.GridSize = GridSize;
CC.BlockSize = BlockSize;
CC.SharedMemory = SharedMemory;
CC.Stream = Stream;
return 0;
}
/// Pop call configuration for kernel launch
unsigned __llvmPopCallConfiguration(dim3 *GridSize, dim3 *BlockSize,
size_t *SharedMemory, void **Stream) {
CallConfigurationTy &CC = ThreadState::getCallConfiguration();
*GridSize = CC.GridSize;
*BlockSize = CC.BlockSize;
*SharedMemory = CC.SharedMemory;
*Stream = CC.Stream;
return 0;
}
unsigned llvmLaunchKernel(const char *KernelID, dim3 GridDim, dim3 BlockDim,
void *KernelArgsPtr, size_t DynamicSharedMem,
void *Stream) {
ol_result_t Result = __llvmLaunchKernelImpl(
KernelID, GridDim, BlockDim, KernelArgsPtr, DynamicSharedMem, Stream);
convertAndSetLastError(Result);
return Result ? Result->Code : 0;
}
} // extern "C"