Skip to content

Commit a390cb2

Browse files
committed
Merge remote-tracking branch 'origin/sycl-web' into llvmspirv_pulldown
2 parents 0948d83 + e3b59a7 commit a390cb2

File tree

15 files changed

+550
-252
lines changed

15 files changed

+550
-252
lines changed

clang/docs/ClangOffloadBundler.rst

Lines changed: 254 additions & 58 deletions
Large diffs are not rendered by default.

clang/include/clang/Driver/OffloadBundler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class OffloadBundler {
7070
llvm::Error UnbundleArchive();
7171
};
7272

73-
/// Obtain the offload kind, real machine triple, and an optional GPUArch
73+
/// Obtain the offload kind, real machine triple, and an optional TargetID
7474
/// out of the target information specified by the user.
7575
/// Bundle Entry ID (or, Offload Target String) has following components:
7676
/// * Offload Kind - Host, OpenMP, or HIP

clang/lib/Driver/OffloadBundler.cpp

Lines changed: 186 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -168,51 +168,6 @@ static std::string getDeviceLibraryFileName(StringRef BundleFileName,
168168
return Result;
169169
}
170170

171-
/// @brief Checks if a code object \p CodeObjectInfo is compatible with a given
172-
/// target \p TargetInfo.
173-
/// @link https://clang.llvm.org/docs/ClangOffloadBundler.html#bundle-entry-id
174-
bool isCodeObjectCompatible(const OffloadTargetInfo &CodeObjectInfo,
175-
const OffloadTargetInfo &TargetInfo) {
176-
177-
// Compatible in case of exact match.
178-
if (CodeObjectInfo == TargetInfo) {
179-
DEBUG_WITH_TYPE("CodeObjectCompatibility",
180-
dbgs() << "Compatible: Exact match: \t[CodeObject: "
181-
<< CodeObjectInfo.str()
182-
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
183-
return true;
184-
}
185-
186-
// Incompatible if Kinds or Triples mismatch.
187-
if (!CodeObjectInfo.isOffloadKindCompatible(TargetInfo.OffloadKind) ||
188-
!CodeObjectInfo.Triple.isCompatibleWith(TargetInfo.Triple)) {
189-
DEBUG_WITH_TYPE(
190-
"CodeObjectCompatibility",
191-
dbgs() << "Incompatible: Kind/Triple mismatch \t[CodeObject: "
192-
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
193-
<< "]\n");
194-
return false;
195-
}
196-
197-
// Incompatible if target IDs are incompatible.
198-
if (!clang::isCompatibleTargetID(CodeObjectInfo.TargetID,
199-
TargetInfo.TargetID)) {
200-
DEBUG_WITH_TYPE(
201-
"CodeObjectCompatibility",
202-
dbgs() << "Incompatible: target IDs are incompatible \t[CodeObject: "
203-
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
204-
<< "]\n");
205-
return false;
206-
}
207-
208-
DEBUG_WITH_TYPE(
209-
"CodeObjectCompatibility",
210-
dbgs() << "Compatible: Code Objects are compatible \t[CodeObject: "
211-
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
212-
<< "]\n");
213-
return true;
214-
}
215-
216171
namespace {
217172
/// Generic file handler interface.
218173
class FileHandler {
@@ -278,6 +233,20 @@ class FileHandler {
278233
});
279234
}
280235

236+
/// Get bundle IDs in \a Input in \a BundleIds.
237+
virtual Error getBundleIDs(MemoryBuffer &Input,
238+
std::set<StringRef> &BundleIds) {
239+
if (Error Err = ReadHeader(Input))
240+
return Err;
241+
return forEachBundle(Input, [&](const BundleInfo &Info) -> Error {
242+
BundleIds.insert(Info.BundleID);
243+
Error Err = listBundleIDsCallback(Input, Info);
244+
if (Err)
245+
return Err;
246+
return Error::success();
247+
});
248+
}
249+
281250
/// For each bundle in \a Input, do \a Func.
282251
Error forEachBundle(MemoryBuffer &Input,
283252
std::function<Error(const BundleInfo &)> Func) {
@@ -1617,6 +1586,99 @@ Error OffloadBundler::ListBundleIDsInFile(
16171586
return FH->listBundleIDs(DecompressedInput);
16181587
}
16191588

1589+
/// @brief Checks if a code object \p CodeObjectInfo is compatible with a given
1590+
/// target \p TargetInfo.
1591+
/// @link https://clang.llvm.org/docs/ClangOffloadBundler.html#bundle-entry-id
1592+
bool isCodeObjectCompatible(const OffloadTargetInfo &CodeObjectInfo,
1593+
const OffloadTargetInfo &TargetInfo) {
1594+
1595+
// Compatible in case of exact match.
1596+
if (CodeObjectInfo == TargetInfo) {
1597+
DEBUG_WITH_TYPE("CodeObjectCompatibility",
1598+
dbgs() << "Compatible: Exact match: \t[CodeObject: "
1599+
<< CodeObjectInfo.str()
1600+
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
1601+
return true;
1602+
}
1603+
1604+
// Incompatible if Kinds or Triples mismatch.
1605+
if (!CodeObjectInfo.isOffloadKindCompatible(TargetInfo.OffloadKind) ||
1606+
!CodeObjectInfo.Triple.isCompatibleWith(TargetInfo.Triple)) {
1607+
DEBUG_WITH_TYPE(
1608+
"CodeObjectCompatibility",
1609+
dbgs() << "Incompatible: Kind/Triple mismatch \t[CodeObject: "
1610+
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
1611+
<< "]\n");
1612+
return false;
1613+
}
1614+
1615+
// Incompatible if Processors mismatch.
1616+
llvm::StringMap<bool> CodeObjectFeatureMap, TargetFeatureMap;
1617+
std::optional<StringRef> CodeObjectProc = clang::parseTargetID(
1618+
CodeObjectInfo.Triple, CodeObjectInfo.TargetID, &CodeObjectFeatureMap);
1619+
std::optional<StringRef> TargetProc = clang::parseTargetID(
1620+
TargetInfo.Triple, TargetInfo.TargetID, &TargetFeatureMap);
1621+
1622+
// Both TargetProc and CodeObjectProc can't be empty here.
1623+
if (!TargetProc || !CodeObjectProc ||
1624+
CodeObjectProc.value() != TargetProc.value()) {
1625+
DEBUG_WITH_TYPE("CodeObjectCompatibility",
1626+
dbgs() << "Incompatible: Processor mismatch \t[CodeObject: "
1627+
<< CodeObjectInfo.str()
1628+
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
1629+
return false;
1630+
}
1631+
1632+
// Incompatible if CodeObject has more features than Target, irrespective of
1633+
// type or sign of features.
1634+
if (CodeObjectFeatureMap.getNumItems() > TargetFeatureMap.getNumItems()) {
1635+
DEBUG_WITH_TYPE("CodeObjectCompatibility",
1636+
dbgs() << "Incompatible: CodeObject has more features "
1637+
"than target \t[CodeObject: "
1638+
<< CodeObjectInfo.str()
1639+
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
1640+
return false;
1641+
}
1642+
1643+
// Compatible if each target feature specified by target is compatible with
1644+
// target feature of code object. The target feature is compatible if the
1645+
// code object does not specify it (meaning Any), or if it specifies it
1646+
// with the same value (meaning On or Off).
1647+
for (const auto &CodeObjectFeature : CodeObjectFeatureMap) {
1648+
auto TargetFeature = TargetFeatureMap.find(CodeObjectFeature.getKey());
1649+
if (TargetFeature == TargetFeatureMap.end()) {
1650+
DEBUG_WITH_TYPE(
1651+
"CodeObjectCompatibility",
1652+
dbgs()
1653+
<< "Incompatible: Value of CodeObject's non-ANY feature is "
1654+
"not matching with Target feature's ANY value \t[CodeObject: "
1655+
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
1656+
<< "]\n");
1657+
return false;
1658+
} else if (TargetFeature->getValue() != CodeObjectFeature.getValue()) {
1659+
DEBUG_WITH_TYPE(
1660+
"CodeObjectCompatibility",
1661+
dbgs() << "Incompatible: Value of CodeObject's non-ANY feature is "
1662+
"not matching with Target feature's non-ANY value "
1663+
"\t[CodeObject: "
1664+
<< CodeObjectInfo.str()
1665+
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
1666+
return false;
1667+
}
1668+
}
1669+
1670+
// CodeObject is compatible if all features of Target are:
1671+
// - either, present in the Code Object's features map with the same sign,
1672+
// - or, the feature is missing from CodeObjects's features map i.e. it is
1673+
// set to ANY
1674+
DEBUG_WITH_TYPE(
1675+
"CodeObjectCompatibility",
1676+
dbgs() << "Compatible: Target IDs are compatible \t[CodeObject: "
1677+
<< CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
1678+
<< "]\n");
1679+
return true;
1680+
}
1681+
16201682
/// Bundle the files. Return true if an error was found.
16211683

16221684
Error OffloadBundler::BundleFiles() {
@@ -1920,13 +1982,81 @@ getCompatibleOffloadTargets(OffloadTargetInfo &CodeObjectInfo,
19201982
return !CompatibleTargets.empty();
19211983
}
19221984

1985+
// Check that each code object file in the input archive conforms to following
1986+
// rule: for a specific processor, a feature either shows up in all target IDs,
1987+
// or does not show up in any target IDs. Otherwise the target ID combination is
1988+
// invalid.
1989+
static Error
1990+
CheckHeterogeneousArchive(StringRef ArchiveName,
1991+
const OffloadBundlerConfig &BundlerConfig) {
1992+
std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
1993+
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1994+
MemoryBuffer::getFileOrSTDIN(ArchiveName, true, false);
1995+
if (std::error_code EC = BufOrErr.getError())
1996+
return createFileError(ArchiveName, EC);
1997+
1998+
ArchiveBuffers.push_back(std::move(*BufOrErr));
1999+
Expected<std::unique_ptr<llvm::object::Archive>> LibOrErr =
2000+
Archive::create(ArchiveBuffers.back()->getMemBufferRef());
2001+
if (!LibOrErr)
2002+
return LibOrErr.takeError();
2003+
2004+
auto Archive = std::move(*LibOrErr);
2005+
2006+
Error ArchiveErr = Error::success();
2007+
auto ChildEnd = Archive->child_end();
2008+
2009+
/// Iterate over all bundled code object files in the input archive.
2010+
for (auto ArchiveIter = Archive->child_begin(ArchiveErr);
2011+
ArchiveIter != ChildEnd; ++ArchiveIter) {
2012+
if (ArchiveErr)
2013+
return ArchiveErr;
2014+
auto ArchiveChildNameOrErr = (*ArchiveIter).getName();
2015+
if (!ArchiveChildNameOrErr)
2016+
return ArchiveChildNameOrErr.takeError();
2017+
2018+
auto CodeObjectBufferRefOrErr = (*ArchiveIter).getMemoryBufferRef();
2019+
if (!CodeObjectBufferRefOrErr)
2020+
return CodeObjectBufferRefOrErr.takeError();
2021+
2022+
auto CodeObjectBuffer =
2023+
MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr, false);
2024+
2025+
Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
2026+
CreateFileHandler(*CodeObjectBuffer, BundlerConfig);
2027+
if (!FileHandlerOrErr)
2028+
return FileHandlerOrErr.takeError();
2029+
2030+
std::unique_ptr<FileHandler> &FileHandler = *FileHandlerOrErr;
2031+
assert(FileHandler);
2032+
2033+
std::set<StringRef> BundleIds;
2034+
auto CodeObjectFileError =
2035+
FileHandler->getBundleIDs(*CodeObjectBuffer, BundleIds);
2036+
if (CodeObjectFileError)
2037+
return CodeObjectFileError;
2038+
2039+
auto &&ConflictingArchs = clang::getConflictTargetIDCombination(BundleIds);
2040+
if (ConflictingArchs) {
2041+
std::string ErrMsg =
2042+
Twine("conflicting TargetIDs [" + ConflictingArchs.value().first +
2043+
", " + ConflictingArchs.value().second + "] found in " +
2044+
ArchiveChildNameOrErr.get() + " of " + ArchiveName)
2045+
.str();
2046+
return createStringError(inconvertibleErrorCode(), ErrMsg);
2047+
}
2048+
}
2049+
2050+
return ArchiveErr;
2051+
}
2052+
19232053
/// UnbundleArchive takes an archive file (".a") as input containing bundled
19242054
/// code object files, and a list of offload targets (not host), and extracts
19252055
/// the code objects into a new archive file for each offload target. Each
19262056
/// resulting archive file contains all code object files corresponding to that
19272057
/// particular offload target. The created archive file does not
19282058
/// contain an index of the symbols and code object files are named as
1929-
/// <<Parent Bundle Name>-<CodeObject's GPUArch>>, with ':' replaced with '_'.
2059+
/// <<Parent Bundle Name>-<CodeObject's TargetID>>, with ':' replaced with '_'.
19302060
Error OffloadBundler::UnbundleArchive() {
19312061
std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
19322062

@@ -1945,6 +2075,16 @@ Error OffloadBundler::UnbundleArchive() {
19452075

19462076
StringRef IFName = BundlerConfig.InputFileNames.front();
19472077

2078+
if (BundlerConfig.CheckInputArchive) {
2079+
// For a specific processor, a feature either shows up in all target IDs, or
2080+
// does not show up in any target IDs. Otherwise the target ID combination
2081+
// is invalid.
2082+
auto ArchiveError = CheckHeterogeneousArchive(IFName, BundlerConfig);
2083+
if (ArchiveError) {
2084+
return ArchiveError;
2085+
}
2086+
}
2087+
19482088
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
19492089
MemoryBuffer::getFileOrSTDIN(IFName, true, false);
19502090
if (std::error_code EC = BufOrErr.getError())

clang/test/Driver/clang-offload-bundler-asserts-on.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@
1616
//
1717
// Create few code object bundles and archive them to create an input archive
1818
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa-gfx906,openmp-amdgcn-amd-amdhsa--gfx908 -input=%t.o -input=%t.tgt1 -input=%t.tgt2 -output=%t.simple.bundle
19-
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx903 -input=%t.o -input=%t.tgt1 -output=%t.simple1.bundle
20-
// RUN: llvm-ar cr %t.input-archive.a %t.simple.bundle %t.simple1.bundle
19+
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx906:sramecc+:xnack+,openmp-amdgcn-amd-amdhsa--gfx908:sramecc+:xnack+ -inputs=%t.o,%t.tgt1,%t.tgt1 -outputs=%t.targetID1.bundle
20+
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx906:sramecc+:xnack-,openmp-amdgcn-amd-amdhsa--gfx908:sramecc+:xnack- -inputs=%t.o,%t.tgt1,%t.tgt1 -outputs=%t.targetID2.bundle
21+
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx906:xnack-,openmp-amdgcn-amd-amdhsa--gfx908:xnack- -inputs=%t.o,%t.tgt1,%t.tgt1 -outputs=%t.targetID3.bundle
22+
// RUN: llvm-ar cr %t.input-archive.a %t.simple.bundle %t.targetID1.bundle %t.targetID2.bundle %t.targetID3.bundle
2123

2224
// Tests to check compatibility between Bundle Entry ID formats i.e. between presence/absence of extra hyphen in case of missing environment field
2325
// RUN: clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa--gfx906,openmp-amdgcn-amd-amdhsa-gfx908 -input=%t.input-archive.a -output=%t-archive-gfx906-simple.a -output=%t-archive-gfx908-simple.a -debug-only=CodeObjectCompatibility 2>&1 | FileCheck %s -check-prefix=BUNDLECOMPATIBILITY
2426
// BUNDLECOMPATIBILITY: Compatible: Exact match: [CodeObject: openmp-amdgcn-amd-amdhsa-gfx906] : [Target: openmp-amdgcn-amd-amdhsa--gfx906]
2527
// BUNDLECOMPATIBILITY: Compatible: Exact match: [CodeObject: openmp-amdgcn-amd-amdhsa--gfx908] : [Target: openmp-amdgcn-amd-amdhsa-gfx908]
2628

2729
// RUN: clang-offload-bundler -unbundle -type=a -targets=hip-amdgcn-amd-amdhsa--gfx906,hipv4-amdgcn-amd-amdhsa-gfx908 -input=%t.input-archive.a -output=%t-hip-archive-gfx906-simple.a -output=%t-hipv4-archive-gfx908-simple.a -hip-openmp-compatible -debug-only=CodeObjectCompatibility 2>&1 | FileCheck %s -check-prefix=HIPOpenMPCOMPATIBILITY
28-
// HIPOpenMPCOMPATIBILITY: Compatible: Code Objects are compatible [CodeObject: openmp-amdgcn-amd-amdhsa-gfx906] : [Target: hip-amdgcn-amd-amdhsa--gfx906]
29-
// HIPOpenMPCOMPATIBILITY: Compatible: Code Objects are compatible [CodeObject: openmp-amdgcn-amd-amdhsa--gfx908] : [Target: hipv4-amdgcn-amd-amdhsa-gfx908]
30+
// HIPOpenMPCOMPATIBILITY: Compatible: Target IDs are compatible [CodeObject: openmp-amdgcn-amd-amdhsa--gfx906] : [Target: hip-amdgcn-amd-amdhsa--gfx906]
31+
// HIPOpenMPCOMPATIBILITY: Compatible: Target IDs are compatible [CodeObject: openmp-amdgcn-amd-amdhsa--gfx908] : [Target: hipv4-amdgcn-amd-amdhsa--gfx908]
3032

3133
// Some code so that we can create a binary out of this file.
3234
int A = 0;

clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ int main(int argc, const char **argv) {
167167
"the output file when bundling object files.\n"),
168168
cl::init(true), cl::cat(ClangOffloadBundlerCategory));
169169

170+
cl::opt<bool> CheckInputArchive(
171+
"check-input-archive",
172+
cl::desc("Check if input heterogeneous archive is "
173+
"valid in terms of TargetID rules.\n"),
174+
cl::init(false), cl::cat(ClangOffloadBundlerCategory));
170175
cl::opt<bool> HipOpenmpCompatible(
171176
"hip-openmp-compatible",
172177
cl::desc("Treat hip and hipv4 offload kinds as "
@@ -204,6 +209,7 @@ int main(int argc, const char **argv) {
204209
// Avoid using cl::opt variables after these assignments when possible
205210
OffloadBundlerConfig BundlerConfig;
206211
BundlerConfig.AllowMissingBundles = AllowMissingBundles;
212+
BundlerConfig.CheckInputArchive = CheckInputArchive;
207213
BundlerConfig.PrintExternalCommands = PrintExternalCommands;
208214
BundlerConfig.AddTargetSymbols = AddTargetSymbols;
209215
BundlerConfig.HipOpenmpCompatible = HipOpenmpCompatible;
@@ -318,6 +324,19 @@ int main(int argc, const char **argv) {
318324
return 0;
319325
}
320326

327+
if (BundlerConfig.CheckInputArchive) {
328+
if (!Unbundle) {
329+
reportError(createStringError(errc::invalid_argument,
330+
"-check-input-archive cannot be used while "
331+
"bundling"));
332+
}
333+
if (Unbundle && BundlerConfig.FilesType != "a") {
334+
reportError(createStringError(errc::invalid_argument,
335+
"-check-input-archive can only be used for "
336+
"unbundling archives (-type=a)"));
337+
}
338+
}
339+
321340
if (OutputFileNames.size() == 0 && !CheckSection) {
322341
reportError(
323342
createStringError(errc::invalid_argument, "no output file specified!"));

libunwind/src/libunwind.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include <sanitizer/asan_interface.h>
2727
#endif
2828

29-
#if !defined(__USING_SJLJ_EXCEPTIONS__)
29+
#if !defined(__USING_SJLJ_EXCEPTIONS__) || !defined(__USING_WASM_EXCEPTIONS__)
3030
#include "AddressSpace.hpp"
3131
#include "UnwindCursor.hpp"
3232

@@ -347,7 +347,8 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
347347
}
348348

349349
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
350-
#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
350+
#endif // !defined(__USING_SJLJ_EXCEPTIONS__) ||
351+
// !defined(__USING_WASM_EXCEPTIONS__)
351352

352353
#ifdef __APPLE__
353354

0 commit comments

Comments
 (0)