diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f034600069eda..4a18697402f91 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7300,8 +7300,10 @@ defm sycl_allow_device_image_dependencies: BoolOptionWithoutMarshalling<"f", "sy def fsycl_dump_device_code_EQ : Joined<["-"], "fsycl-dump-device-code=">, Flags<[NoXarchOption]>, HelpText<"Dump device code into the user provided directory.">; -def fsyclbin : Flag<["-"], "fsyclbin">, - HelpText<"Create a SYCLBIN file">; +def fsyclbin_EQ : Joined<["-"], "fsyclbin=">, Values<"executable,object,input">, + HelpText<"Output in the SYCLBIN binary format in the state specified by  (input, object or executable (default))">; +def fsyclbin : Flag<["-"], "fsyclbin">, Alias, + AliasArgs<["executable"]>; } // let Group = sycl_Group // FIXME: -fsycl-explicit-simd is deprecated. remove it when support is dropped. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 6e10cfd5c7b7b..42938a4a1fe1f 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1230,7 +1230,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) || C.getInputArgs().hasArgNoClaim(options::OPT_fsycl_device_only, - options::OPT_fsyclbin); + options::OPT_fsyclbin_EQ); auto argSYCLIncompatible = [&](OptSpecifier OptId) { if (!IsSYCL) @@ -3470,7 +3470,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, Arg *InputTypeArg = nullptr; bool IsSYCL = Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) || - Args.hasArgNoClaim(options::OPT_fsycl_device_only, options::OPT_fsyclbin); + Args.hasArgNoClaim(options::OPT_fsycl_device_only, + options::OPT_fsyclbin_EQ); // The last /TC or /TP option sets the input type to C or C++ globally. if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC, @@ -7958,7 +7959,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, DDep.add(*FatbinAction, *C.getSingleOffloadToolChain(), nullptr, Action::OFK_HIP); } else if (C.isOffloadingHostKind(Action::OFK_SYCL) && - Args.hasArg(options::OPT_fsyclbin)) { + Args.hasArg(options::OPT_fsyclbin_EQ)) { // With '-fsyclbin', package all the offloading actions into a single output // that is sent to the clang-linker-wrapper. Action *PackagerAction = @@ -9382,7 +9383,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, return C.addResultFile(FinalOutput->getValue(), &JA); // Output to destination for -fsycl-device-only/-fsyclbin and Windows -o if ((offloadDeviceOnly() || - C.getArgs().hasArgNoClaim(options::OPT_fsyclbin)) && + C.getArgs().hasArgNoClaim(options::OPT_fsyclbin_EQ)) && JA.getOffloadingDeviceKind() == Action::OFK_SYCL) if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT__SLASH_o)) return C.addResultFile(FinalOutput->getValue(), &JA); @@ -9556,7 +9557,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, // resulting image. A '.syclbin' extension is used to represent the resulting // output file. if (JA.getOffloadingDeviceKind() == Action::OFK_SYCL && - C.getArgs().hasArgNoClaim(options::OPT_fsyclbin) && + C.getArgs().hasArgNoClaim(options::OPT_fsyclbin_EQ) && JA.getType() == types::TY_Image) { SmallString<128> SYCLBinOutput(getDefaultImageName()); if (IsCLMode()) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a6f29d714e5e8..3e1e63b08c78f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -11508,8 +11508,9 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString("--sycl-target-link-options=" + LinkOptString)); } // Add option to enable creating of the .syclbin file. - if (Args.hasArg(options::OPT_fsyclbin)) - CmdArgs.push_back(Args.MakeArgString("--syclbin")); + if (Arg *A = Args.getLastArg(options::OPT_fsyclbin_EQ)) + CmdArgs.push_back( + Args.MakeArgString("--syclbin=" + StringRef{A->getValue()})); } // Construct the link job so we can wrap around it. diff --git a/clang/test/Driver/fsyclbin.cpp b/clang/test/Driver/fsyclbin.cpp index 43c9e5ec8469b..ad96442462c93 100644 --- a/clang/test/Driver/fsyclbin.cpp +++ b/clang/test/Driver/fsyclbin.cpp @@ -14,17 +14,47 @@ // SYCLBIN_UNUSED: warning: argument unused during compilation: '-fsyclbin' /// Check tool invocation contents. +// RUN: %clangxx -fsycl -fsyclbin=input --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_INPUT +// RUN: %clangxx -fsyclbin=input --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_INPUT +// RUN: %clang_cl -fsycl -fsyclbin=input --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_INPUT +// CHECK_TOOLS_INPUT: clang-offload-packager +// CHECK_TOOLS_INPUT-SAME: --image=file={{.*}}.bc,triple=spir64-unknown-unknown +// CHECK_TOOLS_INPUT-SAME: kind=sycl +// CHECK_TOOLS_INPUT: clang-linker-wrapper +// CHECK_TOOLS_INPUT-SAME: --syclbin=input + +// RUN: %clangxx -fsycl -fsyclbin=object --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_OBJECT +// RUN: %clangxx -fsyclbin=object --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_OBJECT +// RUN: %clang_cl -fsycl -fsyclbin=object --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_OBJECT +// CHECK_TOOLS_OBJECT: clang-offload-packager +// CHECK_TOOLS_OBJECT-SAME: --image=file={{.*}}.bc,triple=spir64-unknown-unknown +// CHECK_TOOLS_OBJECT-SAME: kind=sycl +// CHECK_TOOLS_OBJECT: clang-linker-wrapper +// CHECK_TOOLS_OBJECT-SAME: --syclbin=object + +// RUN: %clangxx -fsycl -fsyclbin=executable --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE +// RUN: %clangxx -fsyclbin=executable --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE +// RUN: %clang_cl -fsycl -fsyclbin=executable --offload-new-driver %s -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE // RUN: %clangxx -fsycl -fsyclbin --offload-new-driver %s -### 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE // RUN: %clangxx -fsyclbin --offload-new-driver %s -### 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE // RUN: %clang_cl -fsycl -fsyclbin --offload-new-driver %s -### 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS -// CHECK_TOOLS: clang-offload-packager -// CHECK_TOOLS-SAME: --image=file={{.*}}.bc,triple=spir64-unknown-unknown -// CHECK_TOOLS-SAME: kind=sycl -// CHECK_TOOLS: clang-linker-wrapper -// CHECK_TOOLS-SAME: --syclbin +// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS_EXECUTABLE +// CHECK_TOOLS_EXECUTABLE: clang-offload-packager +// CHECK_TOOLS_EXECUTABLE-SAME: --image=file={{.*}}.bc,triple=spir64-unknown-unknown +// CHECK_TOOLS_EXECUTABLE-SAME: kind=sycl +// CHECK_TOOLS_EXECUTABLE: clang-linker-wrapper +// CHECK_TOOLS_EXECUTABLE-SAME: --syclbin=executable /// Check compilation phases, only device compile should be performed // RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl -fsyclbin \ diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index a4d2030fb6488..dcb06a3c674bb 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -152,7 +152,9 @@ static std::optional SYCLModuleSplitMode; static bool UseSYCLPostLinkTool; -static bool OutputSYCLBIN; +static bool OutputSYCLBIN = false; + +static SYCLBIN::BundleState SYCLBINState = SYCLBIN::BundleState::Input; static SmallString<128> OffloadImageDumpDir; @@ -2019,7 +2021,6 @@ Expected> linkAndWrapDeviceFiles( // When creating SYCLBIN files, we need to store the compiled modules for // combined packaging. std::mutex SYCLBINModulesMtx; - SYCLBIN::BundleState SYCLBINState = SYCLBIN::BundleState::Input; SmallVector SYCLBINModules; // Initialize the images with any overriding inputs. @@ -2671,7 +2672,25 @@ int main(int Argc, char **Argv) { "-no-use-sycl-post-link-tool options can't " "be used together.")); - OutputSYCLBIN = Args.hasArg(OPT_syclbin); + if (Arg *SYCLBINArg = Args.getLastArg(OPT_syclbin_EQ)) { + OutputSYCLBIN = true; + auto MaybeSYCLBINState = + llvm::StringSwitch>( + SYCLBINArg->getValue()) + .Case("input", SYCLBIN::BundleState::Input) + .Case("object", SYCLBIN::BundleState::Object) + .Case("executable", SYCLBIN::BundleState::Executable) + .Default(std::nullopt); + + if (MaybeSYCLBINState) + SYCLBINState = *MaybeSYCLBINState; + else + reportError( + createStringError("Invalid argument for -syclbin (" + + StringRef{SYCLBINArg->getValue()} + + "). Must be either input, object or executable.")); + } + if (OutputSYCLBIN && Args.hasArg(OPT_sycl_embed_ir)) reportError(createStringError( "-sycl-embed_ir and -syclbin can't be used together.")); diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td index cd07b5660de8a..c1f1af1d0b9cb 100644 --- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td +++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td @@ -238,6 +238,6 @@ def sycl_allow_device_image_dependencies : Flag<["--", "-"], "sycl-allow-device- HelpText<"Allow dependencies between device code images">; // Options to force the output to be of the SYCLBIN format. -def syclbin : Flag<["--", "-"], "syclbin">, +def syclbin_EQ : Joined<["--", "-"], "syclbin=">, Flags<[WrapperOnlyOption]>, - HelpText<"Output in the SYCLBIN binary format">; + HelpText<"Output in the SYCLBIN binary format in the state specified by  (input, object or executable)">; diff --git a/sycl/test/syclbin/simple_kernel.cpp b/sycl/test/syclbin/simple_kernel.cpp index 844b20da3ec5a..f6d1ba18faf3f 100644 --- a/sycl/test/syclbin/simple_kernel.cpp +++ b/sycl/test/syclbin/simple_kernel.cpp @@ -1,5 +1,11 @@ -// RUN: %clangxx --offload-new-driver -fsyclbin -o %t.syclbin %s -// RUN: syclbin-dump %t.syclbin | FileCheck %s +// RUN: %clangxx --offload-new-driver -fsyclbin=input -o %t.input.syclbin %s +// RUN: %clangxx --offload-new-driver -fsyclbin=object -o %t.object.syclbin %s +// RUN: %clangxx --offload-new-driver -fsyclbin=executable -o %t.executable.syclbin %s +// RUN: %clangxx --offload-new-driver -fsyclbin -o %t.default.syclbin %s +// RUN: syclbin-dump %t.input.syclbin | FileCheck %s --check-prefix CHECK-INPUT +// RUN: syclbin-dump %t.object.syclbin | FileCheck %s --check-prefix CHECK-OBJECT +// RUN: syclbin-dump %t.executable.syclbin | FileCheck %s --check-prefix CHECK-EXECUTABLE +// RUN: syclbin-dump %t.default.syclbin | FileCheck %s --check-prefix CHECK-EXECUTABLE // Checks the generated SYCLBIN contents of a simple SYCL free function kernel. @@ -14,17 +20,47 @@ void TestKernel(int *Ptr, int Size) { } } -// CHECK: Version: {{[1-9]+}} -// CHECK-NEXT: Global metadata: -// CHECK-NEXT: SYCLBIN/global metadata: -// CHECK-NEXT: state: 0 -// CHECK-NEXT: Number of Abstract Modules: 1 -// CHECK-NEXT: Abstract Module 0: -// CHECK-NEXT: Metadata: -// CHECK: Number of IR Modules: 1 -// CHECK-NEXT: IR module 0: -// CHECK-NEXT: Metadata: -// CHECK-NEXT: SYCLBIN/ir module metadata: -// CHECK-NEXT: type: 0 -// CHECK-NEXT: Raw IR bytes: -// CHECK-NEXT: Number of Native Device Code Images: 0 +// CHECK-INPUT: Version: {{[1-9]+}} +// CHECK-INPUT-NEXT: Global metadata: +// CHECK-INPUT-NEXT: SYCLBIN/global metadata: +// CHECK-INPUT-NEXT: state: 0 +// CHECK-INPUT-NEXT: Number of Abstract Modules: 1 +// CHECK-INPUT-NEXT: Abstract Module 0: +// CHECK-INPUT-NEXT: Metadata: +// CHECK-INPUT: Number of IR Modules: 1 +// CHECK-INPUT-NEXT: IR module 0: +// CHECK-INPUT-NEXT: Metadata: +// CHECK-INPUT-NEXT: SYCLBIN/ir module metadata: +// CHECK-INPUT-NEXT: type: 0 +// CHECK-INPUT-NEXT: Raw IR bytes: +// CHECK-INPUT-NEXT: Number of Native Device Code Images: 0 + +// CHECK-OBJECT: Version: {{[1-9]+}} +// CHECK-OBJECT-NEXT: Global metadata: +// CHECK-OBJECT-NEXT: SYCLBIN/global metadata: +// CHECK-OBJECT-NEXT: state: 1 +// CHECK-OBJECT-NEXT: Number of Abstract Modules: 1 +// CHECK-OBJECT-NEXT: Abstract Module 0: +// CHECK-OBJECT-NEXT: Metadata: +// CHECK-OBJECT: Number of IR Modules: 1 +// CHECK-OBJECT-NEXT: IR module 0: +// CHECK-OBJECT-NEXT: Metadata: +// CHECK-OBJECT-NEXT: SYCLBIN/ir module metadata: +// CHECK-OBJECT-NEXT: type: 0 +// CHECK-OBJECT-NEXT: Raw IR bytes: +// CHECK-OBJECT-NEXT: Number of Native Device Code Images: 0 + +// CHECK-EXECUTABLE: Version: {{[1-9]+}} +// CHECK-EXECUTABLE-NEXT: Global metadata: +// CHECK-EXECUTABLE-NEXT: SYCLBIN/global metadata: +// CHECK-EXECUTABLE-NEXT: state: 2 +// CHECK-EXECUTABLE-NEXT: Number of Abstract Modules: 1 +// CHECK-EXECUTABLE-NEXT: Abstract Module 0: +// CHECK-EXECUTABLE-NEXT: Metadata: +// CHECK-EXECUTABLE: Number of IR Modules: 1 +// CHECK-EXECUTABLE-NEXT: IR module 0: +// CHECK-EXECUTABLE-NEXT: Metadata: +// CHECK-EXECUTABLE-NEXT: SYCLBIN/ir module metadata: +// CHECK-EXECUTABLE-NEXT: type: 0 +// CHECK-EXECUTABLE-NEXT: Raw IR bytes: +// CHECK-EXECUTABLE-NEXT: Number of Native Device Code Images: 0