Skip to content

Commit f963062

Browse files
[Driver][SYCL] Add support for large device code via a linker script (#6584)
Add -fsycl-huge-device-code as a driver option. When enabled, the driver generates a linker script which directs the linker to place device code later in the binary, which makes it less likely to create a distance larger than that which a PC32 relocation can span. For example, if a 3GB __clang_offload_bundle__ section is placed betwen .text and .rodata, a PC32 relocation to .rodata in the .text is not possible. With this option enabled the device code will be placed after both rather than between them.
1 parent 9b33ad0 commit f963062

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

clang/include/clang/Driver/Options.td

+6
Original file line numberDiff line numberDiff line change
@@ -2867,6 +2867,12 @@ defm sycl_instrument_device_code
28672867
BothFlags<[CC1Option, CoreOption], " Instrumentation and Tracing "
28682868
"Technology (ITT) instrumentation intrinsics calls "
28692869
"(experimental)">>;
2870+
def fsycl_link_huge_device_code : Flag<["-"], "fsycl-link-huge-device-code">,
2871+
Group<sycl_Group>, HelpText<"Generate and use a custom linker script for huge"
2872+
" device code sections">;
2873+
def fno_sycl_link_huge_device_code : Flag<["-"], "fno-sycl-link-huge-device-code">,
2874+
Group<sycl_Group>, HelpText<"Do not generate or use a custom linker script"
2875+
" for huge device code sections (default)">;
28702876
defm sycl_id_queries_fit_in_int: BoolFOption<"sycl-id-queries-fit-in-int",
28712877
LangOpts<"SYCLValueFitInMaxInt">, DefaultTrue,
28722878
PosFlag<SetTrue, [], "Assume">, NegFlag<SetFalse, [], "Do not assume">,

clang/lib/Driver/ToolChains/Gnu.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,56 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
660660
CmdArgs.push_back("-lm");
661661
}
662662

663+
// If requested, use a custom linker script to handle very large device code
664+
// sections.
665+
if (Args.hasArg(options::OPT_fsycl) &&
666+
Args.hasFlag(options::OPT_fsycl_link_huge_device_code,
667+
options::OPT_fno_sycl_link_huge_device_code, false)) {
668+
// Create temporary linker script. Keep it if save-temps is enabled.
669+
const char *LKS;
670+
SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
671+
if (C.getDriver().isSaveTempsEnabled()) {
672+
llvm::sys::path::replace_extension(Name, "ld");
673+
LKS = C.getArgs().MakeArgString(Name.c_str());
674+
} else {
675+
llvm::sys::path::replace_extension(Name, "");
676+
Name = C.getDriver().GetTemporaryPath(Name, "ld");
677+
LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
678+
}
679+
680+
// Add linker script option to the command.
681+
CmdArgs.push_back("-T");
682+
CmdArgs.push_back(LKS);
683+
684+
// If this is not a dry run, create the linker script file.
685+
if (!C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
686+
std::error_code EC;
687+
llvm::raw_fd_ostream ScriptOS(LKS, EC, llvm::sys::fs::OF_None);
688+
689+
if (EC) {
690+
C.getDriver().Diag(clang::diag::err_unable_to_make_temp)
691+
<< EC.message();
692+
} else {
693+
ScriptOS
694+
<< "/*\n"
695+
" * This linker script allows huge (>3GB) device code\n"
696+
" * sections. It has been auto-generated by the SYCL driver.\n"
697+
" */\n"
698+
"SECTIONS\n"
699+
"{\n"
700+
" . = SEGMENT_START(\"sycl-device-code\", .);\n"
701+
" SYCL_DEVICE_CODE ALIGN(CONSTANT (MAXPAGESIZE)) + (. & "
702+
"(CONSTANT (MAXPAGESIZE) - 1)) :\n"
703+
" {\n"
704+
" *(__CLANG_OFFLOAD_BUNDLE__*)\n"
705+
" }\n"
706+
"}\n"
707+
"INSERT AFTER .bss\n";
708+
ScriptOS.close();
709+
}
710+
}
711+
}
712+
663713
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
664714
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
665715
if (IsStatic || IsStaticPIE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// UNSUPPORTED: system-windows
2+
// Test the addition of a custom linker script for huge device code.
3+
4+
// RUN: %clangxx -### -fsycl -fsycl-link-huge-device-code %s 2>&1 | \
5+
// RUN: FileCheck --check-prefix=CHECK-LINKER-SCRIPT %s
6+
// CHECK-LINKER-SCRIPT: "-T" "{{.*}}.ld"
7+
8+
// Also check that a user-provided linker script may be used:
9+
// RUN: %clangxx -### -fsycl -fsycl-link-huge-device-code %s \
10+
// RUN: -T custom-user-script.ld 2>&1 | \
11+
// RUN: FileCheck --check-prefixes=CHECK-USER-SCRIPT %s
12+
// CHECK-USER-SCRIPT: "-T" "custom-user-script.ld"

sycl/doc/UsersManual.md

+8
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ and not recommended to use in production environment.
217217
various events inside JIT generated kernels. These device libraries are
218218
linked in by default.
219219

220+
**`-f[no-]sycl-link-huge-device-code`**
221+
222+
Place device code later in the linked binary in order to avoid precluding
223+
32-bit PC relative relocations between surrounding ELF sections when device
224+
code is larger than 2GiB. This is disabled by default.
225+
226+
NOTE: This option is currently only supported on Linux.
227+
220228
## Intel FPGA specific options
221229

222230
**`-fintelfpga`**

0 commit comments

Comments
 (0)