Skip to content

Commit

Permalink
[SYCL] Update integration header format to match SYCL static
Browse files Browse the repository at this point in the history
library compilation flow.

- Use definitions for kernel_param_kind_t and kernel_param_desc_t
  types from SYCL header.
- Add compiler LIT test.

Signed-off-by: Vladimir Lazarev <[email protected]>
  • Loading branch information
vladimirlaz committed Jan 22, 2019
1 parent 5a3040d commit effac35
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 37 deletions.
5 changes: 2 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ class SYCLIntegrationHeader {
// kernel lambda or function object
enum kernel_param_kind_t {
kind_first,
kind_none = kind_first,
kind_accessor,
kind_accessor = kind_first,
kind_scalar,
kind_struct,
kind_sampler,
Expand Down Expand Up @@ -333,7 +332,7 @@ class SYCLIntegrationHeader {
// Kernel actual parameter descriptor.
struct KernelParamDesc {
// Represents a parameter kind.
kernel_param_kind_t Kind = kind_none;
kernel_param_kind_t Kind = kind_last;
// If Kind is kind_scalar or kind_struct, then
// denotes parameter size in bytes (includes padding for structs)
// If Kind is kind_accessor
Expand Down
44 changes: 10 additions & 34 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,16 +412,17 @@ static void populateIntHeader(SYCLIntegrationHeader &H, const StringRef Name,
QualType NameType, CXXRecordDecl *Lambda) {
ASTContext &Ctx = Lambda->getASTContext();
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Lambda);
KernelParamKind Knd = SYCLIntegrationHeader::kind_none;
KernelParamKind Knd = SYCLIntegrationHeader::kind_last;
H.startKernel(Name, NameType);
unsigned Offset = 0;
int Info = 0;

auto Vis = std::make_tuple(
// pre_visit
[&](int CaptureN, VarDecl *CapturedVar, FieldDecl *CapturedVal) {
// Set offset in bytes
Offset = static_cast<unsigned>(
Layout.getFieldOffset(CapturedVal->getFieldIndex()));
Layout.getFieldOffset(CapturedVal->getFieldIndex()))/8;
},
// visit_accessor
[&](int CaptureN, target AccTrg, QualType PointeeType,
Expand Down Expand Up @@ -516,7 +517,6 @@ static const char *paramKind2Str(KernelParamKind K) {
case SYCLIntegrationHeader::kind_##x: \
return "kind_" #x
switch (K) {
CASE(none);
CASE(accessor);
CASE(scalar);
CASE(struct);
Expand Down Expand Up @@ -664,37 +664,15 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
}
O << "\n";

O << "#include <CL/sycl/detail/kernel_desc.hpp>\n";

O << "\n";

O << "namespace cl {\n";
O << "namespace sycl {\n";
O << "namespace detail {\n";

O << "// kernel parameter kinds\n";
O << "enum kernel_param_kind_t {\n";

for (int I = SYCLIntegrationHeader::kind_first;
I <= SYCLIntegrationHeader::kind_last; I++) {
KernelParamKind It = static_cast<KernelParamKind>(I);
O << " " << std::string(paramKind2Str(It));
if (I < SYCLIntegrationHeader::kind_last)
O << ",";
O << "\n";
}
O << "};\n";
O << "\n";
O << "// describes a kernel parameter\n";
O << "struct kernel_param_desc_t {\n";
O << " // parameter kind\n";
O << " kernel_param_kind_t kind;\n";
O << " // kind == kind_scalar, kind_struct\n";
O << " // parameter size in bytes (includes padding for structs)\n";
O << " // kind == kind_accessor\n";
O << " // access target; possible access targets are defined in "
"access/access.hpp\n";
O << " int info;\n";
O << " // offset of the captured value of the parameter in the lambda or "
"function object\n";
O << " int offs;\n";
O << "};\n\n";

O << "// names of all kernels defined in the corresponding source\n";
O << "static constexpr\n";
Expand All @@ -720,11 +698,9 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {

for (const auto &P : K.Params) {
std::string TyStr = paramKind2Str(P.Kind);
O << " { " << TyStr << ", " << P.Info << ", " << P.Offset << " },\n";
O << " { kernel_param_kind_t::" << TyStr << ", ";
O << P.Info << ", " << P.Offset << " },\n";
}
O << " { kind_none, 0, 0 }";
if (I < KernelDescs.size() - 1)
O << ",";
O << "\n";
}
O << "};\n\n";
Expand Down Expand Up @@ -772,7 +748,7 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
O << " return kernel_signatures[i+" << CurStart << "];\n";
O << " }\n";
O << "};\n";
CurStart += N + 1;
CurStart += N;
}
O << "\n";
O << "} // namespace detail\n";
Expand Down
135 changes: 135 additions & 0 deletions clang/test/CodeGenSYCL/integration_header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// RUN: %clang --sycl -Xclang -fsycl-int-header=%t.h %s -c -o %T/kernel.spv
// RUN: FileCheck -input-file=%t.h %s
//
// CHECK: class first_kernel;
// CHECK-NEXT: template <typename T> class second_kernel;
// CHECK-NEXT: struct X;
// CHECK-NEXT: template <typename T> struct point ;
// CHECK-NEXT: template <int a, typename T1, typename T2> class third_kernel;
//
// CHECK: #include <CL/sycl/detail/kernel_desc.hpp>
//
// CHECK: static constexpr
// CHECK-NEXT: const char* const kernel_names[] = {
// CHECK-NEXT: "first_kernel",
// CHECK-NEXT: "second_namespace::second_kernel<char>",
// CHECK-NEXT: "third_kernel<1, int, point< X> >"
// CHECK-NEXT: };
//
// CHECK: const kernel_param_desc_t kernel_signatures[] = {
// CHECK-NEXT: //--- first_kernel
// CHECK-NEXT: { kernel_param_kind_t::kind_scalar, 4, 0 },
// CHECK-NEXT: { kernel_param_kind_t::kind_accessor, 2014, 4 },
// CHECK-NEXT: { kernel_param_kind_t::kind_accessor, 2016, 5 },
// CHECK-EMPTY:
// CHECK-NEXT: //--- second_namespace::second_kernel<char>
// CHECK-NEXT: { kernel_param_kind_t::kind_scalar, 4, 0 },
// CHECK-NEXT: { kernel_param_kind_t::kind_accessor, 2016, 4 },
// CHECK-EMPTY:
// CHECK-NEXT: //--- third_kernel<1, int, point< X> >
// CHECK-NEXT: { kernel_param_kind_t::kind_scalar, 4, 0 },
// CHECK-NEXT: { kernel_param_kind_t::kind_accessor, 2016, 4 },
// CHECK-EMPTY:
// CHECK-NEXT: };
//
// CHECK: template <class KernelNameType> struct KernelInfo;
// CHECK: template <> struct KernelInfo<class first_kernel> {
// CHECK: template <> struct KernelInfo<class second_namespace::second_kernel<char>> {
// CHECK: template <> struct KernelInfo<class third_kernel<1, int, struct point<struct X> >> {

namespace cl {
namespace sycl {
namespace access {

enum class target {
global_buffer = 2014,
constant_buffer,
local,
image,
host_buffer,
host_image,
image_array
};

enum class mode {
read = 1024,
write,
read_write,
discard_write,
discard_read_write,
atomic
};

enum class placeholder { false_t,
true_t };

enum class address_space : int {
private_space = 0,
global_space,
constant_space,
local_space
};
} // namespace access
template <typename dataT, int dimensions, access::mode accessmode,
access::target accessTarget = access::target::global_buffer,
access::placeholder isPlaceholder = access::placeholder::false_t>
class accessor {

public:
void use(void) const {}
};
} // namespace sycl
} // namespace cl

template <typename KernelName, typename KernelType>
__attribute__((sycl_kernel)) void kernel_single_task(KernelType kernelFunc) {
kernelFunc();
}
struct x {};
template <typename T>
struct point {};
namespace second_namespace {
template <typename T>
class second_kernel;
}

template <int a, typename T1, typename T2>
class third_kernel;

int main() {

cl::sycl::accessor<char, 1, cl::sycl::access::mode::read> acc1;
cl::sycl::accessor<float, 2, cl::sycl::access::mode::write,
cl::sycl::access::target::local,
cl::sycl::access::placeholder::true_t>
acc2;
int i = 13;
// TODO: Uncomemnt when structures in kernel arguments are correctly processed
// by SYCL compiler
/* struct {
char c;
int i;
} test_s;
test_s.c = 14;*/
kernel_single_task<class first_kernel>([=]() {
if (i == 13 /*&& test_s.c == 14*/) {

acc1.use();
acc2.use();
}
});

kernel_single_task<class second_namespace::second_kernel<char>>([=]() {
if (i == 13) {
acc2.use();
}
});
kernel_single_task<class third_kernel<1, int,point<struct X>>>([=]() {
if (i == 13) {
acc2.use();
}
});

return 0;
}

0 comments on commit effac35

Please sign in to comment.