diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 7b003aab3eb33..8e5b2afdcb976 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -111,4 +111,5 @@ TYPE("fpga_aocx", FPGA_AOCX, INVALID, "aocx", phases TYPE("fpga_aocr", FPGA_AOCR, INVALID, "aocr", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("fpga_aoco", FPGA_AOCO, INVALID, "aoco", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("fpga_dependencies", FPGA_Dependencies, INVALID, "d", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("fpga_dependencies_list", FPGA_Dependencies_List, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("none", Nothing, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index c24a6f3765f26..46a82dce89c8a 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -150,7 +150,8 @@ bool Compilation::CleanupFileList(const TempFileList &Files, // Temporary file lists contain files that need to be cleaned. The // file containing the information is also removed if (File.second == types::TY_Tempfilelist || - File.second == types::TY_Tempfiletable) { + File.second == types::TY_Tempfiletable || + File.second == types::TY_FPGA_Dependencies_List) { // These are temporary files and need to be removed. bool IsTable = File.second == types::TY_Tempfiletable; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 836219453b682..b3e3a6655ae62 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3612,6 +3612,9 @@ class OffloadingActionBuilder final { /// List of objects to extract FPGA dependency info from ActionList FPGAObjectInputs; + /// List of static archives to extract FPGA dependency info from + ActionList FPGAArchiveInputs; + /// List of CUDA architectures to use in this compilation with NVPTX targets. SmallVector GpuArchList; @@ -4060,15 +4063,19 @@ class OffloadingActionBuilder final { // triple calls for it (provided a valid subarch). ActionList BEInputs; BEInputs.push_back(BuildCodeAction); - for (Action *A : FPGAObjectInputs) { - // Send any known objects through the unbundler to grab the - // dependency file associated. + auto unbundleAdd = [&](Action *A, types::ID T) { ActionList AL; AL.push_back(A); - Action *UnbundleAction = C.MakeAction( - AL, types::TY_FPGA_Dependencies); + Action *UnbundleAction = + C.MakeAction(AL, T); BEInputs.push_back(UnbundleAction); - } + }; + // Send any known objects/archives through the unbundler to grab the + // dependency file associated. + for (Action *A : FPGAObjectInputs) + unbundleAdd(A, types::TY_FPGA_Dependencies); + for (Action *A : FPGAArchiveInputs) + unbundleAdd(A, types::TY_FPGA_Dependencies_List); for (const auto &A : DeviceLibObjects) BEInputs.push_back(A); BuildCodeAction = @@ -4193,6 +4200,7 @@ class OffloadingActionBuilder final { Arg *SYCLAddTargets = Args.getLastArg(options::OPT_fsycl_add_targets_EQ); bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false); + bool SYCLfpgaTriple = false; if (SYCLTargets || SYCLAddTargets) { if (SYCLTargets) { llvm::StringMap FoundNormalizedTriples; @@ -4210,6 +4218,8 @@ class OffloadingActionBuilder final { FoundNormalizedTriples[NormalizedName] = Val; SYCLTripleList.push_back(TT); + if (TT.getSubArch() == llvm::Triple::SPIRSubArch_fpga) + SYCLfpgaTriple = true; } } if (SYCLAddTargets) { @@ -4233,6 +4243,8 @@ class OffloadingActionBuilder final { const char *SYCLTargetArch = SYCLfpga ? "spir64_fpga" : "spir64"; SYCLTripleList.push_back( C.getDriver().MakeSYCLDeviceTriple(SYCLTargetArch)); + if (SYCLfpga) + SYCLfpgaTriple = true; } // Set the FPGA output type based on command line (-fsycl-link). @@ -4240,6 +4252,21 @@ class OffloadingActionBuilder final { FPGAOutType = (A->getValue() == StringRef("early")) ? types::TY_FPGA_AOCR : types::TY_FPGA_AOCX; + // Populate FPGA static archives that could contain dep files to be + // incorporated into the aoc compilation + if (SYCLfpgaTriple) { + SmallVector LinkArgs(getLinkerArgs(C, Args)); + for (const StringRef &LA : LinkArgs) { + if (isStaticArchiveFile(LA) && hasOffloadSections(C, LA, Args)) { + const llvm::opt::OptTable &Opts = C.getDriver().getOpts(); + Arg *InputArg = MakeInputArg(Args, Opts, Args.MakeArgString(LA)); + Action *Current = + C.MakeAction(*InputArg, types::TY_Archive); + FPGAArchiveInputs.push_back(Current); + } + } + } + DeviceLinkerInputs.resize(ToolChains.size()); return initializeGpuArchMap(); } @@ -5975,12 +6002,14 @@ InputInfo Driver::BuildJobsForActionNoCache( // Do a check for a dependency file unbundle for FPGA. This is out of line // from a regular unbundle, so just create and return the name of the // unbundled file. - if (JA->getType() == types::TY_FPGA_Dependencies) { + if (JA->getType() == types::TY_FPGA_Dependencies || + JA->getType() == types::TY_FPGA_Dependencies_List) { + std::string Ext(types::getTypeTempSuffix(JA->getType())); std::string TmpFileName = - C.getDriver().GetTemporaryPath(llvm::sys::path::stem(BaseInput), "d"); + C.getDriver().GetTemporaryPath(llvm::sys::path::stem(BaseInput), Ext); const char *TmpFile = C.addTempFile(C.getArgs().MakeArgString(TmpFileName)); - Result = InputInfo(types::TY_FPGA_Dependencies, TmpFile, TmpFile); + Result = InputInfo(JA->getType(), TmpFile, TmpFile); UnbundlingResults.push_back(Result); } else { // Now that we have all the results generated, select the one that should diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 064acb6de4b17..14f3201c8914f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7378,7 +7378,8 @@ void OffloadBundler::ConstructJobMultipleOutputs( bool IsMSVCEnv = C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); types::ID InputType(Input.getType()); - bool IsFPGADepUnbundle = (JA.getType() == types::TY_FPGA_Dependencies); + bool IsFPGADepUnbundle = JA.getType() == types::TY_FPGA_Dependencies; + bool IsFPGADepLibUnbundle = JA.getType() == types::TY_FPGA_Dependencies_List; bool IsArchiveUnbundle = (!IsMSVCEnv && C.getDriver().getOffloadStaticLibSeen() && (types::isArchive(InputType) || InputType == types::TY_Object)); @@ -7394,7 +7395,7 @@ void OffloadBundler::ConstructJobMultipleOutputs( else TypeArg = "aoo"; } - if (InputType == types::TY_FPGA_AOCO || + if (InputType == types::TY_FPGA_AOCO || IsFPGADepLibUnbundle || (IsMSVCEnv && types::isArchive(InputType))) TypeArg = "aoo"; if (IsFPGADepUnbundle) @@ -7453,7 +7454,7 @@ void OffloadBundler::ConstructJobMultipleOutputs( Triples += Dep.DependentBoundArch; } } - if (IsFPGADepUnbundle) { + if (IsFPGADepUnbundle || IsFPGADepLibUnbundle) { // TODO - We are currently using the target triple inputs to slot a location // of the dependency information into the bundle. It would be good to // separate this out to an explicit option in the bundler for the dependency @@ -7474,7 +7475,7 @@ void OffloadBundler::ConstructJobMultipleOutputs( // When dealing with -fintelfpga, there is an additional unbundle step // that occurs for the dependency file. In that case, do not use the // dependent information, but just the output file. - if (IsFPGADepUnbundle) + if (IsFPGADepUnbundle || IsFPGADepLibUnbundle) UB += Outputs[0].getFilename(); else { for (unsigned I = 0; I < Outputs.size(); ++I) { diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp index f3b58dd3d50f6..ec1c9699c1980 100644 --- a/clang/lib/Driver/ToolChains/SYCL.cpp +++ b/clang/lib/Driver/ToolChains/SYCL.cpp @@ -225,7 +225,8 @@ void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C, // Add any FPGA library lists. These come in as special tempfile lists. CmdArgs.push_back(Args.MakeArgString(Twine("-library-list=") + Filename)); - else if (II.getType() == types::TY_FPGA_Dependencies) + else if (II.getType() == types::TY_FPGA_Dependencies || + II.getType() == types::TY_FPGA_Dependencies_List) FPGADepFiles.push_back(II); else CmdArgs.push_back(C.getArgs().MakeArgString(Filename)); @@ -279,6 +280,8 @@ void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C, for (unsigned I = 0; I < FPGADepFiles.size(); ++I) { if (I) DepOpt += ','; + if (FPGADepFiles[I].getType() == types::TY_FPGA_Dependencies_List) + DepOpt += "@"; DepOpt += FPGADepFiles[I].getFilename(); } CmdArgs.push_back(C.getArgs().MakeArgString(DepOpt)); diff --git a/clang/test/Driver/sycl-intelfpga-static-lib-win.cpp b/clang/test/Driver/sycl-intelfpga-static-lib-win.cpp new file mode 100644 index 0000000000000..2f61c8d9567d4 --- /dev/null +++ b/clang/test/Driver/sycl-intelfpga-static-lib-win.cpp @@ -0,0 +1,33 @@ +/// +/// tests specific to -fintelfpga -fsycl w/ static libs +/// +// REQUIRES: clang-driver +// REQUIRES: system-windows + +// make dummy archive +// Build a fat static lib that will be used for all tests +// RUN: echo "void foo(void) {}" > %t1.cpp +// RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -fintelfpga %t1.cpp -c -o %t1_bundle.obj +// RUN: lib -out:%t.lib %t1_bundle.obj + +/// Check phases with static lib +// RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -fintelfpga %t.lib -ccc-print-phases 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK_PHASES %s +// CHECK_PHASES: 0: input, "[[INPUT:.+\.lib]]", object, (host-sycl) +// CHECK_PHASES: 1: linker, {0}, image, (host-sycl) +// CHECK_PHASES: 2: input, "[[INPUT]]", archive +// CHECK_PHASES: 3: clang-offload-unbundler, {2}, archive +// CHECK_PHASES: 4: linker, {3}, ir, (device-sycl) +// CHECK_PHASES: 5: sycl-post-link, {4}, ir, (device-sycl) +// CHECK_PHASES: 6: llvm-spirv, {5}, spirv, (device-sycl) +// CHECK_PHASES: 7: input, "[[INPUT]]", archive +// CHECK_PHASES: 8: clang-offload-unbundler, {7}, fpga_dependencies_list +// CHECK_PHASES: 9: backend-compiler, {6, 8}, fpga_aocx, (device-sycl) +// CHECK_PHASES: 10: clang-offload-wrapper, {9}, object, (device-sycl) +// CHECK_PHASES: 11: offload, "host-sycl (x86_64-pc-windows-msvc)" {1}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {10}, image + +/// Check for unbundle and use of deps in static lib +// RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -fintelfpga %t.lib -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK_UNBUNDLE %s +// CHECK_UNBUNDLE: clang-offload-bundler" "-type=aoo" "-targets=sycl-fpga_dep" "-inputs={{.*}}" "-outputs=[[DEPFILES:.+\.txt]]" "-unbundle" +// CHECK_UNBUNDLE: aoc{{.*}} "-dep-files=@[[DEPFILES]]" diff --git a/clang/test/Driver/sycl-intelfpga-static-lib.cpp b/clang/test/Driver/sycl-intelfpga-static-lib.cpp new file mode 100644 index 0000000000000..510684ddaed7f --- /dev/null +++ b/clang/test/Driver/sycl-intelfpga-static-lib.cpp @@ -0,0 +1,33 @@ +/// +/// tests specific to -fintelfpga -fsycl w/ static libs +/// +// REQUIRES: clang-driver + +// make dummy archive +// Build a fat static lib that will be used for all tests +// RUN: echo "void foo(void) {}" > %t1.cpp +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fintelfpga -fsycl %t1.cpp -c -o %t1_bundle.o +// RUN: llvm-ar cr %t.a %t1_bundle.o + +/// Check phases with static lib +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga %t.a -ccc-print-phases 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK_PHASES %s +// CHECK_PHASES: 0: input, "[[INPUT:.+\.a]]", object, (host-sycl) +// CHECK_PHASES: 1: linker, {0}, image, (host-sycl) +// CHECK_PHASES: 2: input, "[[INPUT]]", archive +// CHECK_PHASES: 3: partial-link, {2}, object +// CHECK_PHASES: 4: clang-offload-unbundler, {3}, object +// CHECK_PHASES: 5: linker, {4}, ir, (device-sycl) +// CHECK_PHASES: 6: sycl-post-link, {5}, ir, (device-sycl) +// CHECK_PHASES: 7: llvm-spirv, {6}, spirv, (device-sycl) +// CHECK_PHASES: 8: input, "[[INPUT]]", archive +// CHECK_PHASES: 9: clang-offload-unbundler, {8}, fpga_dependencies_list +// CHECK_PHASES: 10: backend-compiler, {7, 9}, fpga_aocx, (device-sycl) +// CHECK_PHASES: 11: clang-offload-wrapper, {10}, object, (device-sycl) +// CHECK_PHASES: 12: offload, "host-sycl (x86_64-unknown-linux-gnu)" {1}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {11}, image + +/// Check for unbundle and use of deps in static lib +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga %t.a -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK_UNBUNDLE %s +// CHECK_UNBUNDLE: clang-offload-bundler" "-type=aoo" "-targets=sycl-fpga_dep" "-inputs={{.*}}" "-outputs=[[DEPFILES:.+\.txt]]" "-unbundle" +// CHECK_UNBUNDLE: aoc{{.*}} "-dep-files=@[[DEPFILES]]" diff --git a/clang/test/Driver/sycl-offload-intelfpga.cpp b/clang/test/Driver/sycl-offload-intelfpga.cpp index de589affbc5e7..eec759afa5a22 100644 --- a/clang/test/Driver/sycl-offload-intelfpga.cpp +++ b/clang/test/Driver/sycl-offload-intelfpga.cpp @@ -368,11 +368,13 @@ // CHK-FPGA-AOCO-PHASES: 15: linker, {11, 14}, ir, (device-sycl) // CHK-FPGA-AOCO-PHASES: 16: sycl-post-link, {15}, ir, (device-sycl) // CHK-FPGA-AOCO-PHASES: 17: llvm-spirv, {16}, spirv, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 18: input, "[[INPUTA]]", fpga_aoco -// CHK-FPGA-AOCO-PHASES: 19: clang-offload-unbundler, {18}, fpga_aoco -// CHK-FPGA-AOCO-PHASES: 20: backend-compiler, {17, 19}, fpga_aocx, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 21: clang-offload-wrapper, {20}, object, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 22: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {21}, image +// CHK-FPGA-AOCO-PHASES: 18: input, "[[INPUTA]]", archive +// CHK-FPGA-AOCO-PHASES: 19: clang-offload-unbundler, {18}, fpga_dependencies_list +// CHK-FPGA-AOCO-PHASES: 20: input, "[[INPUTA]]", fpga_aoco +// CHK-FPGA-AOCO-PHASES: 21: clang-offload-unbundler, {20}, fpga_aoco +// CHK-FPGA-AOCO-PHASES: 22: backend-compiler, {17, 19, 21}, fpga_aocx, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 23: clang-offload-wrapper, {22}, object, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 24: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {23}, image /// FPGA AOCO Windows phases check // RUN: %clang_cl -fsycl -fintelfpga -foffload-static-lib=%t_aoco_cl.a %s -### -ccc-print-phases 2>&1 \ @@ -394,11 +396,13 @@ // CHK-FPGA-AOCO-PHASES-WIN: 14: linker, {11, 13}, ir, (device-sycl) // CHK-FPGA-AOCO-PHASES-WIN: 15: sycl-post-link, {14}, ir, (device-sycl) // CHK-FPGA-AOCO-PHASES-WIN: 16: llvm-spirv, {15}, spirv, (device-sycl) -// CHK-FPGA-AOCO-PHASES-WIN: 17: input, "[[INPUTA]]", fpga_aoco -// CHK-FPGA-AOCO-PHASES-WIN: 18: clang-offload-unbundler, {17}, fpga_aoco -// CHK-FPGA-AOCO-PHASES-WIN: 19: backend-compiler, {16, 18}, fpga_aocx, (device-sycl) -// CHK-FPGA-AOCO-PHASES-WIN: 20: clang-offload-wrapper, {19}, object, (device-sycl) -// CHK-FPGA-AOCO-PHASES-WIN: 21: offload, "host-sycl (x86_64-pc-windows-msvc)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {20}, image +// CHK-FPGA-AOCO-PHASES-WIN: 17: input, "[[INPUTA]]", archive +// CHK-FPGA-AOCO-PHASES-WIN: 18: clang-offload-unbundler, {17}, fpga_dependencies_list +// CHK-FPGA-AOCO-PHASES-WIN: 19: input, "[[INPUTA]]", fpga_aoco +// CHK-FPGA-AOCO-PHASES-WIN: 20: clang-offload-unbundler, {19}, fpga_aoco +// CHK-FPGA-AOCO-PHASES-WIN: 21: backend-compiler, {16, 18, 20}, fpga_aocx, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 22: clang-offload-wrapper, {21}, object, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 23: offload, "host-sycl (x86_64-pc-windows-msvc)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {22}, image /// aoco test, checking tools // RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga -foffload-static-lib=%t_aoco.a -### %s 2>&1 \