Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions clang/test/Driver/linker-wrapper-image.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
// REQUIRES: amdgpu-registered-target
// REQUIRES: spirv-registered-target

// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.elf.o

Expand Down Expand Up @@ -263,3 +264,37 @@
// HIP: while.end:
// HIP-NEXT: ret void
// HIP-NEXT: }

// RUN: clang-offload-packager -o %t.out --image=file=%t.elf.o,kind=sycl,triple=spirv64-unknown-unknown,arch=generic
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
// RUN: -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=SYCL
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu -r \
// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=SYCL

// SYCL: %__sycl.tgt_device_image = type { i16, i8, i8, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }
// SYCL-NEXT: %__sycl.tgt_bin_desc = type { i16, i16, ptr, ptr, ptr }

// SYCL: @.sycl_offloading.target.0 = internal unnamed_addr constant [1 x i8] zeroinitializer
// SYCL-NEXT: @.sycl_offloading.opts.compile.0 = internal unnamed_addr constant [1 x i8] zeroinitializer
// SYCL-NEXT: @.sycl_offloading.opts.link.0 = internal unnamed_addr constant [1 x i8] zeroinitializer
// SYCL-NEXT: @.sycl_offloading.0.data = internal unnamed_addr constant [0 x i8] zeroinitializer
// SYCL-NEXT: @.sycl_offloading.0.info = internal local_unnamed_addr constant [2 x i64] [i64 ptrtoint (ptr @.sycl_offloading.0.data to i64), i64 0], section ".tgtimg", align 16
// SYCL-NEXT: @llvm.used = appending global [1 x ptr] [ptr @.sycl_offloading.0.info], section "llvm.metadata"
// SYCL-NEXT: @.sycl_offloading.device_images = internal unnamed_addr constant [1 x %__sycl.tgt_device_image] [%__sycl.tgt_device_image { i16 3, i8 8, i8 0, ptr @.sycl_offloading.target.0, ptr @.sycl_offloading.opts.compile.0, ptr @.sycl_offloading.opts.link.0, ptr @.sycl_offloading.0.data, ptr @.sycl_offloading.0.data, ptr null, ptr null, ptr null, ptr null }]
// SYCL-NEXT: @.sycl_offloading.descriptor = internal constant %__sycl.tgt_bin_desc { i16 1, i16 1, ptr @.sycl_offloading.device_images, ptr null, ptr null }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just copied from OpenMP?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RUN lines are copied from OpenMP and adjusted to SYCL case. Output's checks are copied from the clang-linker-wrapper's output.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm just wondering why everything's called tgt_bin_desc and similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, we customized old clang-offload-wrapper and then we extracted SYCL logic in a separate place. That is how these names stuck with us.

// SYCL-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @sycl.descriptor_reg, ptr null }]
// SYCL-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @sycl.descriptor_unreg, ptr null }]

// SYCL: define internal void @sycl.descriptor_reg() section ".text.startup" {
// SYCL-NEXT: entry:
// SYCL-NEXT: call void @__sycl_register_lib(ptr @.sycl_offloading.descriptor)
// SYCL-NEXT: ret void
// SYCL-NEXT: }

// SYCL: define internal void @sycl.descriptor_unreg() section ".text.startup" {
// SYCL-NEXT: entry:
// SYCL-NEXT: call void @__sycl_unregister_lib(ptr @.sycl_offloading.descriptor)
// SYCL-NEXT: ret void
// SYCL-NEXT: }
2 changes: 1 addition & 1 deletion clang/test/Driver/linker-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ __attribute__((visibility("protected"), used)) int x;
// RUN: clang-offload-packager -o %t.out \
// RUN: --image=file=%t.spirv.bc,kind=sycl,triple=spirv64-unknown-unknown,arch=generic
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: not clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=SPIRV-LINK

// SPIRV-LINK: clang{{.*}} -o {{.*}}.img --target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker -triple=spirv64-unknown-unknown -Xlinker -arch=
Expand Down
1 change: 1 addition & 0 deletions clang/tools/clang-linker-wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(LLVM_LINK_COMPONENTS
CodeGen
LTO
FrontendOffloading
FrontendSYCL
)

set(LLVM_TARGET_DEFINITIONS LinkerWrapperOpts.td)
Expand Down
41 changes: 40 additions & 1 deletion clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/Frontend/Offloading/OffloadWrapper.h"
#include "llvm/Frontend/Offloading/Utility.h"
#include "llvm/Frontend/SYCL/OffloadWrapper.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Module.h"
Expand Down Expand Up @@ -711,6 +712,13 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
M, BuffersToWrap.front(), offloading::getOffloadEntryArray(M)))
return std::move(Err);
break;
case OFK_SYCL: {
offloading::sycl::SYCLWrappingOptions WrappingOptions;
if (Error Err = offloading::sycl::wrapSYCLBinaries(M, BuffersToWrap,
WrappingOptions))
return Err;
break;
}
default:
return createStringError(getOffloadKindName(Kind) +
" wrapping is not supported");
Expand Down Expand Up @@ -748,6 +756,36 @@ bundleOpenMP(ArrayRef<OffloadingImage> Images) {
return std::move(Buffers);
}

Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
bundleSYCL(ArrayRef<OffloadingImage> Images) {
SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just return this back here, right?

  if (DryRun) {
    // In dry-run mode there is an empty input which is insufficient for
    // the testing. Therefore, we insert a stub value.
    OffloadingImage Image;
    Image.TheOffloadKind = OffloadKind::OFK_SYCL;
    Image.Image = MemoryBuffer::getMemBufferCopy("");
    SmallString<0> SerializedImage = OffloadBinary::write(Image);
    Buffers.emplace_back(MemoryBuffer::getMemBufferCopy(SerializedImage));
    return Buffers;
  }

if (DryRun) {
// In dry-run mode there is an empty input which is insufficient for
// the testing. Therefore, we insert a stub value.
OffloadBinary::OffloadingImage Image;
Image.TheOffloadKind = OffloadKind::OFK_SYCL;
Image.Image = MemoryBuffer::getMemBufferCopy("");
SmallString<0> SerializedImage = OffloadBinary::write(Image);
Buffers.emplace_back(MemoryBuffer::getMemBufferCopy(SerializedImage));
return Buffers;
}

for (const OffloadingImage &TheImage : Images) {
SmallVector<OffloadFile> OffloadBinaries;
if (Error E = extractOffloadBinaries(*TheImage.Image, OffloadBinaries))
return E;

for (const OffloadFile &File : OffloadBinaries) {
const OffloadBinary &Binary = *File.getBinary();
SmallString<0> SerializedImage =
OffloadBinary::write(Binary.getOffloadingImage());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is throwing me for a loop a bit and I'm probably missing some context, an OffloadingImage is just a C++ format that is used to create the offloading binary. Once the binary has been created why do we need to then go backwards to a C++ struct that contains the same information?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's time for us to meet and discuss all questions during a call. I'll put together some slides and contact you by email to schedule a call.

Buffers.emplace_back(MemoryBuffer::getMemBufferCopy(SerializedImage));
}
}

return Buffers;
}

Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
bundleCuda(ArrayRef<OffloadingImage> Images, const ArgList &Args) {
SmallVector<std::pair<StringRef, StringRef>, 4> InputFiles;
Expand Down Expand Up @@ -800,8 +838,9 @@ bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args,
llvm::TimeTraceScope TimeScope("Bundle linked output");
switch (Kind) {
case OFK_OpenMP:
case OFK_SYCL:
return bundleOpenMP(Images);
case OFK_SYCL:
return bundleSYCL(Images);
case OFK_Cuda:
return bundleCuda(Images, Args);
case OFK_HIP:
Expand Down
44 changes: 44 additions & 0 deletions llvm/include/llvm/Frontend/SYCL/OffloadWrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//===----- OffloadWrapper.h -------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_FRONTEND_SYCL_OFFLOAD_WRAPPER_H
#define LLVM_FRONTEND_SYCL_OFFLOAD_WRAPPER_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/OffloadBinary.h"

#include <string>

namespace llvm {

class Module;

namespace offloading {
namespace sycl {

struct SYCLWrappingOptions {
// target/compiler specific options what are suggested to use to "compile"
// program at runtime.
std::string CompileOptions;
// Target/Compiler specific options that are suggested to use to "link"
// program at runtime.
std::string LinkOptions;
};

/// Wraps OffloadBinaries in the given \p Buffers into the module \p M
/// as global symbols and registers the images with the SYCL Runtime.
/// \param Options Settings that allows to turn on optional data and settings.
llvm::Error
wrapSYCLBinaries(llvm::Module &M, llvm::ArrayRef<llvm::ArrayRef<char>> Buffers,
SYCLWrappingOptions Options = SYCLWrappingOptions());

} // namespace sycl
} // namespace offloading
} // namespace llvm

#endif // LLVM_FRONTEND_SYCL_OFFLOAD_WRAPPER_H
9 changes: 6 additions & 3 deletions llvm/include/llvm/Object/OffloadBinary.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum ImageKind : uint16_t {
IMG_Cubin,
IMG_Fatbinary,
IMG_PTX,
IMG_SPIRV,
IMG_LAST,
};

Expand All @@ -70,9 +71,9 @@ class OffloadBinary : public Binary {

/// The offloading metadata that will be serialized to a memory buffer.
struct OffloadingImage {
ImageKind TheImageKind;
OffloadKind TheOffloadKind;
uint32_t Flags;
ImageKind TheImageKind = ImageKind::IMG_None;
OffloadKind TheOffloadKind = OffloadKind::OFK_None;
uint32_t Flags = 0;
MapVector<StringRef, StringRef> StringData;
std::unique_ptr<MemoryBuffer> Image;
};
Expand All @@ -84,6 +85,8 @@ class OffloadBinary : public Binary {
/// Serialize the contents of \p File to a binary buffer to be read later.
LLVM_ABI static SmallString<0> write(const OffloadingImage &);

OffloadingImage getOffloadingImage() const;

static uint64_t getAlignment() { return 8; }

ImageKind getImageKind() const { return TheEntry->TheImageKind; }
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ add_subdirectory(HLSL)
add_subdirectory(OpenACC)
add_subdirectory(OpenMP)
add_subdirectory(Offloading)
add_subdirectory(SYCL)
14 changes: 14 additions & 0 deletions llvm/lib/Frontend/SYCL/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
add_llvm_component_library(LLVMFrontendSYCL
OffloadWrapper.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/SYCL

LINK_COMPONENTS
Core
FrontendOffloading
Object
Support
TransformUtils
)
Loading
Loading