diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 6732ba80d02a5..aa96b0e8b31d5 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2867,6 +2867,12 @@ defm sycl_instrument_device_code BothFlags<[CC1Option, CoreOption], " Instrumentation and Tracing " "Technology (ITT) instrumentation intrinsics calls " "(experimental)">>; +def fsycl_link_huge_device_code : Flag<["-"], "fsycl-link-huge-device-code">, + Group, HelpText<"Generate and use a custom linker script for huge" + " device code sections">; +def fno_sycl_link_huge_device_code : Flag<["-"], "fno-sycl-link-huge-device-code">, + Group, HelpText<"Do not generate or use a custom linker script" + " for huge device code sections (default)">; defm sycl_id_queries_fit_in_int: BoolFOption<"sycl-id-queries-fit-in-int", LangOpts<"SYCLValueFitInMaxInt">, DefaultTrue, PosFlag, NegFlag, diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 88f44512d42dc..3067017cb2485 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -660,6 +660,56 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lm"); } + // If requested, use a custom linker script to handle very large device code + // sections. + if (Args.hasArg(options::OPT_fsycl) && + Args.hasFlag(options::OPT_fsycl_link_huge_device_code, + options::OPT_fno_sycl_link_huge_device_code, false)) { + // Create temporary linker script. Keep it if save-temps is enabled. + const char *LKS; + SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); + if (C.getDriver().isSaveTempsEnabled()) { + llvm::sys::path::replace_extension(Name, "ld"); + LKS = C.getArgs().MakeArgString(Name.c_str()); + } else { + llvm::sys::path::replace_extension(Name, ""); + Name = C.getDriver().GetTemporaryPath(Name, "ld"); + LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); + } + + // Add linker script option to the command. + CmdArgs.push_back("-T"); + CmdArgs.push_back(LKS); + + // If this is not a dry run, create the linker script file. + if (!C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { + std::error_code EC; + llvm::raw_fd_ostream ScriptOS(LKS, EC, llvm::sys::fs::OF_None); + + if (EC) { + C.getDriver().Diag(clang::diag::err_unable_to_make_temp) + << EC.message(); + } else { + ScriptOS + << "/*\n" + " * This linker script allows huge (>3GB) device code\n" + " * sections. It has been auto-generated by the SYCL driver.\n" + " */\n" + "SECTIONS\n" + "{\n" + " . = SEGMENT_START(\"sycl-device-code\", .);\n" + " SYCL_DEVICE_CODE ALIGN(CONSTANT (MAXPAGESIZE)) + (. & " + "(CONSTANT (MAXPAGESIZE) - 1)) :\n" + " {\n" + " *(__CLANG_OFFLOAD_BUNDLE__*)\n" + " }\n" + "}\n" + "INSERT AFTER .bss\n"; + ScriptOS.close(); + } + } + } + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { if (IsStatic || IsStaticPIE) diff --git a/clang/test/Driver/sycl-huge-device-code-linker-script.cpp b/clang/test/Driver/sycl-huge-device-code-linker-script.cpp new file mode 100644 index 0000000000000..0761fa0cc412a --- /dev/null +++ b/clang/test/Driver/sycl-huge-device-code-linker-script.cpp @@ -0,0 +1,12 @@ +// UNSUPPORTED: system-windows +// Test the addition of a custom linker script for huge device code. + +// RUN: %clangxx -### -fsycl -fsycl-link-huge-device-code %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-LINKER-SCRIPT %s +// CHECK-LINKER-SCRIPT: "-T" "{{.*}}.ld" + +// Also check that a user-provided linker script may be used: +// RUN: %clangxx -### -fsycl -fsycl-link-huge-device-code %s \ +// RUN: -T custom-user-script.ld 2>&1 | \ +// RUN: FileCheck --check-prefixes=CHECK-USER-SCRIPT %s +// CHECK-USER-SCRIPT: "-T" "custom-user-script.ld" diff --git a/sycl/doc/UsersManual.md b/sycl/doc/UsersManual.md index 0a089f61ca472..60c295d503dc2 100644 --- a/sycl/doc/UsersManual.md +++ b/sycl/doc/UsersManual.md @@ -217,6 +217,14 @@ and not recommended to use in production environment. various events inside JIT generated kernels. These device libraries are linked in by default. +**`-f[no-]sycl-link-huge-device-code`** + + Place device code later in the linked binary in order to avoid precluding + 32-bit PC relative relocations between surrounding ELF sections when device + code is larger than 2GiB. This is disabled by default. + + NOTE: This option is currently only supported on Linux. + ## Intel FPGA specific options **`-fintelfpga`**