Author: Yaxun (Sam) Liu Date: 2020-12-16T14:52:39-05:00 New Revision: b9fb063e63c7959e8bc9b424bd34b266ca826826
URL: https://github.com/llvm/llvm-project/commit/b9fb063e63c7959e8bc9b424bd34b266ca826826 DIFF: https://github.com/llvm/llvm-project/commit/b9fb063e63c7959e8bc9b424bd34b266ca826826.diff LOG: [clang-offload-bundler] Add option -allow-missing-bundles There are out-of-tree tools using clang-offload-bundler to extract bundles from bundled files. When a bundle is not in the bundled file, clang-offload-bundler is expected to emit an error message and return non-zero value. However currently clang-offload-bundler silently generates empty file for the missing bundles. Since OpenMP/HIP toolchains expect the current behavior, an option -allow-missing-bundles is added to let clang-offload-bundler create empty file when a bundle is missing when unbundling. The unbundling job action is updated to use this option by default. clang-offload-bundler itself will emit error when a bundle is missing when unbundling by default. Changes are also made to check duplicate targets in -targets option and emit error. Differential Revision: https://reviews.llvm.org/D93068 Added: Modified: clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/clang-offload-bundler.c clang/test/Driver/hip-toolchain-rdc-separate.hip clang/test/Driver/openmp-offload.c clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1c1224f3990b..6ec6a551fafe 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7392,6 +7392,7 @@ void OffloadBundler::ConstructJobMultipleOutputs( } CmdArgs.push_back(TCArgs.MakeArgString(UB)); CmdArgs.push_back("-unbundle"); + CmdArgs.push_back("-allow-missing-bundles"); // All the inputs are encoded as commands. C.addCommand(std::make_unique<Command>( diff --git a/clang/test/Driver/clang-offload-bundler.c b/clang/test/Driver/clang-offload-bundler.c index 21699e78dda6..b4bab6bbd1e8 100644 --- a/clang/test/Driver/clang-offload-bundler.c +++ b/clang/test/Driver/clang-offload-bundler.c @@ -33,6 +33,7 @@ // CK-HELP: {{.*}}one. The resulting file can also be unbundled into diff erent files by // CK-HELP: {{.*}}this tool if -unbundle is provided. // CK-HELP: {{.*}}USAGE: clang-offload-bundler [options] +// CK-HELP: {{.*}}-allow-missing-bundles {{.*}}- Create empty files if bundles are missing when unbundling // CK-HELP: {{.*}}-inputs=<string> - [<input file>,...] // CK-HELP: {{.*}}-outputs=<string> - [<output file>,...] // CK-HELP: {{.*}}-targets=<string> - [<offload kind>-<target triple>,...] @@ -88,7 +89,7 @@ // RUN: not clang-offload-bundler -type=i -targets=openmp-powerpc64le-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR9A // RUN: not clang-offload-bundler -type=i -targets=host-%itanium_abi_triple,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR9B // CK-ERR9A: error: expecting exactly one host target but got 0 -// CK-ERR9B: error: expecting exactly one host target but got 2 +// CK-ERR9B: error: Duplicate targets are not allowed // // Check text bundle. This is a readable format, so we check for the format we expect to find. @@ -181,17 +182,17 @@ // RUN: diff %t.tgt2 %t.res.tgt2 // Check if we can unbundle a file with no magic strings. -// RUN: clang-offload-bundler -type=s -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.s,%t.res.tgt1,%t.res.tgt2 -inputs=%t.s -unbundle +// RUN: clang-offload-bundler -type=s -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.s,%t.res.tgt1,%t.res.tgt2 -inputs=%t.s -unbundle -allow-missing-bundles // RUN: diff %t.s %t.res.s // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 -// RUN: clang-offload-bundler -type=s -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.s,%t.res.tgt2 -inputs=%t.s -unbundle +// RUN: clang-offload-bundler -type=s -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.s,%t.res.tgt2 -inputs=%t.s -unbundle -allow-missing-bundles // RUN: diff %t.s %t.res.s // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 // Check that bindler prints an error if given host bundle does not exist in the fat binary. -// RUN: not clang-offload-bundler -type=s -targets=host-x86_64-xxx-linux-gnu,openmp-powerpc64le-ibm-linux-gnu -outputs=%t.res.s,%t.res.tgt1 -inputs=%t.bundle3.s -unbundle 2>&1 | FileCheck %s --check-prefix CK-NO-HOST-BUNDLE +// RUN: not clang-offload-bundler -type=s -targets=host-x86_64-xxx-linux-gnu,openmp-powerpc64le-ibm-linux-gnu -outputs=%t.res.s,%t.res.tgt1 -inputs=%t.bundle3.s -unbundle -allow-missing-bundles 2>&1 | FileCheck %s --check-prefix CK-NO-HOST-BUNDLE // CK-NO-HOST-BUNDLE: error: Can't find bundle for the host target // @@ -229,11 +230,11 @@ // RUN: diff %t.tgt1 %t.res.tgt1 // Check if we can unbundle a file with no magic strings. -// RUN: clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.bc,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bc -unbundle +// RUN: clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.bc,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bc -unbundle -allow-missing-bundles // RUN: diff %t.bc %t.res.bc // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 -// RUN: clang-offload-bundler -type=bc -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.bc,%t.res.tgt2 -inputs=%t.bc -unbundle +// RUN: clang-offload-bundler -type=bc -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.bc,%t.res.tgt2 -inputs=%t.bc -unbundle -allow-missing-bundles // RUN: diff %t.bc %t.res.bc // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 @@ -269,11 +270,11 @@ // RUN: diff %t.tgt1 %t.res.tgt1 // Check if we can unbundle a file with no magic strings. -// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%t.o -unbundle +// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%t.o -unbundle -allow-missing-bundles // RUN: diff %t.o %t.res.o // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 -// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%t.o -unbundle +// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%t.o -unbundle -allow-missing-bundles // RUN: diff %t.o %t.res.o // RUN: diff %t.empty %t.res.tgt1 // RUN: diff %t.empty %t.res.tgt2 @@ -288,6 +289,36 @@ // RUN: diff %t.tgt1 %t.res.tgt1 // RUN: diff %t.tgt2 %t.res.tgt2 +// +// Check error due to missing bundles +// +// RUN: clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa-gfx900 -inputs=%t.bc,%t.tgt1 -outputs=%t.hip.bundle.bc +// RUN: not clang-offload-bundler -type=bc -inputs=%t.hip.bundle.bc -outputs=%t.tmp.bc -unbundle \ +// RUN: -targets=hip-amdgcn-amd-amdhsa-gfx906 \ +// RUN: 2>&1 | FileCheck -check-prefix=MISS1 %s +// RUN: not clang-offload-bundler -type=bc -inputs=%t.hip.bundle.bc -outputs=%t.tmp.bc,%t.tmp2.bc -unbundle \ +// RUN: -targets=hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx900 \ +// RUN: 2>&1 | FileCheck -check-prefix=MISS1 %s +// MISS1: error: Can't find bundles for hip-amdgcn-amd-amdhsa-gfx906 +// RUN: not clang-offload-bundler -type=bc -inputs=%t.hip.bundle.bc -outputs=%t.tmp.bc,%t.tmp2.bc -unbundle \ +// RUN: -targets=hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx803 \ +// RUN: 2>&1 | FileCheck -check-prefix=MISS2 %s +// MISS2: error: Can't find bundles for hip-amdgcn-amd-amdhsa-gfx803 and hip-amdgcn-amd-amdhsa-gfx906 +// RUN: not clang-offload-bundler -type=bc -inputs=%t.hip.bundle.bc -outputs=%t.tmp.bc,%t.tmp2.bc,%t.tmp3.bc -unbundle \ +// RUN: -targets=hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx1010 \ +// RUN: 2>&1 | FileCheck -check-prefix=MISS3 %s +// MISS3: error: Can't find bundles for hip-amdgcn-amd-amdhsa-gfx1010, hip-amdgcn-amd-amdhsa-gfx803, and hip-amdgcn-amd-amdhsa-gfx906 + +// +// Check error due to duplicate targets +// +// RUN: not clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa-gfx900,hip-amdgcn-amd-amdhsa-gfx900 \ +// RUN: -inputs=%t.bc,%t.tgt1,%t.tgt1 -outputs=%t.hip.bundle.bc 2>&1 | FileCheck -check-prefix=DUP %s +// RUN: not clang-offload-bundler -type=bc -inputs=%t.hip.bundle.bc -outputs=%t.tmp.bc,%t.tmp2.bc -unbundle \ +// RUN: -targets=hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx906 \ +// RUN: 2>&1 | FileCheck -check-prefix=DUP %s +// DUP: error: Duplicate targets are not allowed + // Some code so that we can create a binary out of this file. int A = 0; void test_func(void) { diff --git a/clang/test/Driver/hip-toolchain-rdc-separate.hip b/clang/test/Driver/hip-toolchain-rdc-separate.hip index 5cf1b4f26850..979b90fee046 100644 --- a/clang/test/Driver/hip-toolchain-rdc-separate.hip +++ b/clang/test/Driver/hip-toolchain-rdc-separate.hip @@ -87,22 +87,22 @@ // LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o" // LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900" // LINK-SAME: "-inputs=[[A_O:.*a.o]]" "-outputs=[[A_OBJ_HOST:.*o]],{{.*o}},{{.*o}}" -// LINK: "-unbundle" +// LINK: "-unbundle" "-allow-missing-bundles" // LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o" // LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900" // LINK-SAME: "-inputs=[[B_O:.*b.o]]" "-outputs=[[B_OBJ_HOST:.*o]],{{.*o}},{{.*o}}" -// LINK: "-unbundle" +// LINK: "-unbundle" "-allow-missing-bundles" // LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o" // LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900" // LINK-SAME: "-inputs=[[A_O]]" "-outputs={{.*o}},[[A_BC1:.*o]],[[A_BC2:.*o]]" -// LINK: "-unbundle" +// LINK: "-unbundle" "-allow-missing-bundles" // LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o" // LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900" // LINK-SAME: "-inputs=[[B_O]]" "-outputs={{.*o}},[[B_BC1:.*o]],[[B_BC2:.*o]]" -// LINK: "-unbundle" +// LINK: "-unbundle" "-allow-missing-bundles" // LINK-NOT: "*.llvm-link" // LINK-NOT: ".*opt" diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index d32632059f58..8be535b02c82 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -495,7 +495,7 @@ // CHK-UBJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBJOBS-SAME: [[HOSTPP:[^\\/]+\.i]], // CHK-UBJOBS-SAME: [[T1PP:[^\\/]+\.i]], -// CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" +// CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" "-allow-missing-bundles" // CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " @@ -504,7 +504,7 @@ // CHK-UBJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]], // CHK-UBJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]], -// CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" +// CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" "-allow-missing-bundles" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " @@ -563,7 +563,7 @@ // CHK-UBJOBS2-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs= // CHK-UBJOBS2-SAME: [[HOSTOBJ:[^\\/]+\.o]], // CHK-UBJOBS2-SAME: [[T1OBJ:[^\\/]+\.o]], -// CHK-UBJOBS2-SAME: [[T2OBJ:[^\\/]+\.o]]" "-unbundle" +// CHK-UBJOBS2-SAME: [[T2OBJ:[^\\/]+\.o]]" "-unbundle" "-allow-missing-bundles" // CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS2-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" // CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" " @@ -579,7 +579,7 @@ // CHK-UBJOBS2-ST-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs= // CHK-UBJOBS2-ST-SAME: [[HOSTOBJ:[^\\/,]+\.o]], // CHK-UBJOBS2-ST-SAME: [[T1OBJ:[^\\/,]+\.o]], -// CHK-UBJOBS2-ST-SAME: [[T2OBJ:[^\\/,]+\.o]]" "-unbundle" +// CHK-UBJOBS2-ST-SAME: [[T2OBJ:[^\\/,]+\.o]]" "-unbundle" "-allow-missing-bundles" // CHK-UBJOBS2-ST-NOT: clang-offload-bundler{{.*}}in.so // CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS2-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]" @@ -609,7 +609,7 @@ // CHK-UBUJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBUJOBS-SAME: [[HOSTPP:[^\\/]+\.i]], // CHK-UBUJOBS-SAME: [[T1PP:[^\\/]+\.i]], -// CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" +// CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" "-allow-missing-bundles" // CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" @@ -617,7 +617,7 @@ // CHK-UBUJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBUJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]], // CHK-UBUJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]], -// CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" +// CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" "-allow-missing-bundles" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index a1b2fecb4a80..1e2a2a67bcce 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -43,6 +43,7 @@ #include <cstdint> #include <forward_list> #include <memory> +#include <set> #include <string> #include <system_error> #include <utility> @@ -95,6 +96,12 @@ static cl::opt<bool> PrintExternalCommands( "instead of actually executing them - for testing purposes.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); +static cl::opt<bool> + AllowMissingBundles("allow-missing-bundles", + cl::desc("Create empty files if bundles are missing " + "when unbundling.\n"), + cl::init(false), cl::cat(ClangOffloadBundlerCategory)); + static cl::opt<unsigned> BundleAlignment("bundle-align", cl::desc("Alignment of bundle for binary files"), @@ -883,6 +890,25 @@ static Error UnbundleFiles() { FoundHostBundle = true; } + if (!AllowMissingBundles && !Worklist.empty()) { + std::string ErrMsg = "Can't find bundles for"; + std::set<StringRef> Sorted; + for (auto &E : Worklist) + Sorted.insert(E.first()); + unsigned I = 0; + unsigned Last = Sorted.size() - 1; + for (auto &E : Sorted) { + if (I != 0 && Last > 1) + ErrMsg += ","; + ErrMsg += " "; + if (I == Last && I != 0) + ErrMsg += "and "; + ErrMsg += E.str(); + ++I; + } + return createStringError(inconvertibleErrorCode(), ErrMsg); + } + // If no bundles were found, assume the input file is the host bundle and // create empty files for the remaining targets. if (Worklist.size() == TargetNames.size()) { @@ -974,7 +1000,15 @@ int main(int argc, const char **argv) { // have exactly one host target. unsigned Index = 0u; unsigned HostTargetNum = 0u; + llvm::DenseSet<StringRef> ParsedTargets; for (StringRef Target : TargetNames) { + if (ParsedTargets.contains(Target)) { + reportError(createStringError(errc::invalid_argument, + "Duplicate targets are not allowed")); + return 1; + } + ParsedTargets.insert(Target); + StringRef Kind; StringRef Triple; getOffloadKindAndTriple(Target, Kind, Triple); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits