# Clang 23.1.0 documentation

## Clang SYCL Linker

## Introduction

This tool works as a wrapper around the SYCL device code linking process. The purpose of this tool is to provide an interface to link SYCL device bitcode in LLVM IR format together with LLVM bitcode libraries, and then run SPIR-V code generation on the fully linked device code to produce the final output. After the linking stage, the fully linked device code in LLVM IR format may undergo several SYCL-specific finalization steps before the SPIR-V code generation step. The tool will also support the Ahead-Of-Time (AOT) compilation flow. AOT compilation is the process of invoking the back-end at compile time to produce the final binary, as opposed to just-in-time (JIT) compilation when final code generation is deferred until application runtime.

Device code linking for SYCL offloading has known quirks that make it difficult to use in a unified offloading setting. The primary issue is that several finalization steps are required to be run on the fully linked LLVM IR bitcode to guarantee conformance to SYCL standards. This step is unique to the SYCL offloading compilation flow.

This tool has been proposed to work around this issue.

## Usage

This tool can be used with the following options. Several of these options will be passed down to downstream AOT compilation tools like ‘ocloc’ and ‘opencl-aot’.

    OVERVIEW: A utility that wraps around the SYCL device code linking process.
    This enables LLVM IR linking, post-linking and code generation for SPIR-V
    JIT and AOT targets.

    USAGE: clang-sycl-linker [options] <input bitcode files>

    OPTIONS:
      --arch <value>                Specify the name of the target architecture.
      --dry-run                     Print generated commands without running.
      -help-hidden                  Display all available options
      -help                         Display available options (--help-hidden for more)
      -L <dir>                      Add <dir> to the library search path
      -l <libname>                  Search for library <libname>
      --whole-archive               Include all archive members in the link
      --no-whole-archive            Only include archive members that resolve undefined symbols (default)
      -u <symbol>                   Force undefined symbol during linking
      --module-split-mode=<mode>    Module split mode: 'translation_unit' (default), 'kernel', or 'link_unit'
      --ocloc-options=<value>       Options passed to ocloc for Intel GPU AOT compilation
      --opencl-aot-options=<value>  Options passed to opencl-aot for Intel CPU AOT compilation
      -o <path>                     Path to file to write output
      --save-temps                  Save intermediate results
      --triple <value>              Specify the target triple.
      --version                     Display the version number and exit
      -v                            Print verbose information
      -spirv-dump-device-code=<dir> Directory to dump SPIR-V IR code into

## Library Linking

Device bitcode libraries can be packaged into archive libraries (`.a` files) using `llvm-ar` and linked using the `-l` option:

    llvm-ar rc libdevice.a func1.bc func2.bc func3.bc
    clang-sycl-linker input.bc -l device -L /path/to/libs

The linker supports standard archive library search semantics:

- `-l <name>` searches for `lib<name>.a` in the directories specified by `-L`

- `-l :<exact-name>` searches for the exact filename in the `-L` paths

- Absolute paths can be passed as positional arguments: `clang-sycl-linker input.bc /path/to/libdevice.a`

By default, archive linking is lazy - only archive members (individual `.bc` files) that resolve undefined symbols are extracted and linked. This happens at file granularity: if any symbol in a `.bc` file is needed, all symbols in that file are included. The linker uses a symbol-driven fixed-point algorithm: it repeatedly scans archives to extract members that resolve currently undefined symbols until no more extractions occur.

To force extraction of all archive members regardless of symbol resolution, use `--whole-archive`:

    clang-sycl-linker input.bc --whole-archive -l device --no-whole-archive -l other

The `-u <symbol>` option can be used to force a symbol to be undefined, which can trigger extraction of archive members that define that symbol:

    clang-sycl-linker input.bc -u my_init_function -l device

## Examples

### Basic Usage

This tool is intended to be invoked when targeting any of the target offloading toolchains. When the –sycl-link option is passed to the clang driver, the driver will invoke the linking job of the target offloading toolchain, which in turn will invoke this tool. This tool can be used to create one or more fully linked device images that are ready to be wrapped and linked with host code to generate the final executable.

    clang-sycl-linker --triple spirv64 --arch bmg_g21 input.bc

### Linking with Device Libraries

To link device bitcode libraries, first package them into archive files:

    # Create device library archives
    llvm-ar rc libmath.a sin.bc cos.bc tan.bc
    llvm-ar rc libutils.a helper1.bc helper2.bc

    # Link with lazy loading (only needed members extracted)
    clang-sycl-linker --triple spirv64 kernel.bc -l math -l utils -L /path/to/libs -o kernel.spv

    # Force all members to be included from libmath.a
    clang-sycl-linker --triple spirv64 kernel.bc --whole-archive -l math --no-whole-archive -l utils -L /path/to/libs -o kernel.spv

    # Use exact archive filename or absolute path
    clang-sycl-linker --triple spirv64 kernel.bc -l :libmath.a -L /path/to/libs -o kernel.spv
    clang-sycl-linker --triple spirv64 kernel.bc /absolute/path/libmath.a -o kernel.spv