Skip to content

Commit 5fc91a5

Browse files
Merge branch 'sycl' into refactorcache
2 parents 66f4928 + 6927aef commit 5fc91a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1220
-774
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13038,6 +13038,8 @@ def err_free_function_first_occurrence_missing_attr: Error<
1303813038
"the first occurrence of SYCL kernel free function should be declared with 'sycl-nd-range-kernel' or 'sycl-single-task-kernel' compile time properties">;
1303913039
def err_free_function_class_method : Error<
1304013040
"%select{static |}0class method cannot be used to define a SYCL kernel free function kernel">;
13041+
def err_sycl_kernel_virtual_arg : Error<
13042+
"argument type '%0' virtually inherited from base class `%1` is not supported as a SYCL kernel argument">;
1304113043

1304213044

1304313045
// SYCL kernel entry point diagnostics

clang/lib/Driver/ToolChains/SYCL.cpp

Lines changed: 139 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,141 @@ static bool checkPVCDevice(std::string SingleArg, std::string &DevArg) {
426426
return false;
427427
}
428428

429+
#if !defined(_WIN32)
430+
static void
431+
addSYCLDeviceSanitizerLibs(const Compilation &C, bool IsSpirvAOT,
432+
StringRef LibSuffix,
433+
SmallVector<std::string, 8> &LibraryList) {
434+
const llvm::opt::ArgList &Args = C.getArgs();
435+
enum { JIT = 0, AOT_CPU, AOT_DG2, AOT_PVC };
436+
auto addSingleLibrary = [&](StringRef DeviceLibName) {
437+
SmallString<128> LibName(DeviceLibName);
438+
llvm::sys::path::replace_extension(LibName, LibSuffix);
439+
LibraryList.push_back(Args.MakeArgString(LibName));
440+
};
441+
442+
// This function is used to check whether there is only one GPU device
443+
// (PVC or DG2) specified in AOT compilation mode. If yes, we can use
444+
// corresponding libsycl-asan-* to improve device sanitizer performance,
445+
// otherwise stick to fallback device sanitizer library used in JIT mode.
446+
auto getSpecificGPUTarget = [](const ArgStringList &CmdArgs) -> size_t {
447+
std::string DeviceArg = getDeviceArg(CmdArgs);
448+
if ((DeviceArg.empty()) || (DeviceArg.find(",") != std::string::npos))
449+
return JIT;
450+
451+
std::string Temp;
452+
if (checkPVCDevice(DeviceArg, Temp))
453+
return AOT_PVC;
454+
455+
if (DeviceArg == "dg2")
456+
return AOT_DG2;
457+
458+
return JIT;
459+
};
460+
461+
auto getSingleBuildTarget = [&]() -> size_t {
462+
if (!IsSpirvAOT)
463+
return JIT;
464+
465+
llvm::opt::Arg *SYCLTarget = Args.getLastArg(options::OPT_fsycl_targets_EQ);
466+
if (!SYCLTarget || (SYCLTarget->getValues().size() != 1))
467+
return JIT;
468+
469+
StringRef SYCLTargetStr = SYCLTarget->getValue();
470+
if (SYCLTargetStr.starts_with("spir64_x86_64"))
471+
return AOT_CPU;
472+
473+
if (SYCLTargetStr == "intel_gpu_pvc")
474+
return AOT_PVC;
475+
476+
if (SYCLTargetStr.starts_with("intel_gpu_dg2"))
477+
return AOT_DG2;
478+
479+
if (SYCLTargetStr.starts_with("spir64_gen")) {
480+
ArgStringList TargArgs;
481+
Args.AddAllArgValues(TargArgs, options::OPT_Xs, options::OPT_Xs_separate);
482+
Args.AddAllArgValues(TargArgs, options::OPT_Xsycl_backend);
483+
llvm::opt::Arg *A = nullptr;
484+
if ((A = Args.getLastArg(options::OPT_Xsycl_backend_EQ)) &&
485+
StringRef(A->getValue()).starts_with("spir64_gen"))
486+
TargArgs.push_back(A->getValue(1));
487+
488+
return getSpecificGPUTarget(TargArgs);
489+
}
490+
491+
return JIT;
492+
};
493+
494+
std::string SanitizeVal;
495+
size_t sanitizer_lib_idx = getSingleBuildTarget();
496+
if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ,
497+
options::OPT_fno_sanitize_EQ)) {
498+
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
499+
A->getValues().size() == 1) {
500+
SanitizeVal = A->getValue();
501+
}
502+
} else {
503+
// User can pass -fsanitize=address to device compiler via
504+
// -Xsycl-target-frontend, sanitize device library must be
505+
// linked with user's device image if so.
506+
std::vector<std::string> EnabledDeviceSanitizers;
507+
508+
// NOTE: "-fsanitize=" applies to all device targets
509+
auto SyclFEArgVals = Args.getAllArgValues(options::OPT_Xsycl_frontend);
510+
auto SyclFEEQArgVals = Args.getAllArgValues(options::OPT_Xsycl_frontend_EQ);
511+
auto ArchDeviceVals = Args.getAllArgValues(options::OPT_Xarch_device);
512+
513+
std::vector<std::string> ArgVals(
514+
SyclFEArgVals.size() + SyclFEEQArgVals.size() + ArchDeviceVals.size());
515+
ArgVals.insert(ArgVals.end(), SyclFEArgVals.begin(), SyclFEArgVals.end());
516+
ArgVals.insert(ArgVals.end(), SyclFEEQArgVals.begin(),
517+
SyclFEEQArgVals.end());
518+
ArgVals.insert(ArgVals.end(), ArchDeviceVals.begin(), ArchDeviceVals.end());
519+
520+
// Driver will report error if more than one of address sanitizer, memory
521+
// sanitizer or thread sanitizer is enabled, so we only need to check first
522+
// one here.
523+
for (const std::string &Arg : ArgVals) {
524+
if (Arg.find("-fsanitize=address") != std::string::npos) {
525+
SanitizeVal = "address";
526+
break;
527+
}
528+
if (Arg.find("-fsanitize=memory") != std::string::npos) {
529+
SanitizeVal = "memory";
530+
break;
531+
}
532+
if (Arg.find("-fsanitize=thread") != std::string::npos) {
533+
SanitizeVal = "thread";
534+
break;
535+
}
536+
}
537+
}
538+
539+
const SmallVector<StringRef, 5> SYCLDeviceAsanLibs = {
540+
"libsycl-asan", "libsycl-asan-cpu", "libsycl-asan-dg2",
541+
"libsycl-asan-pvc"};
542+
const SmallVector<StringRef, 5> SYCLDeviceMsanLibs = {
543+
"libsycl-msan", "libsycl-msan-cpu",
544+
// Currently, we only provide aot msan libdevice for PVC and CPU.
545+
// For DG2, we just use libsycl-msan as placeholder.
546+
"libsycl-msan", "libsycl-msan-pvc"};
547+
const SmallVector<StringRef, 5> SYCLDeviceTsanLibs = {
548+
"libsycl-tsan", "libsycl-tsan-cpu",
549+
// Currently, we only provide aot tsan libdevice for PVC and CPU.
550+
// For DG2, we just use libsycl-tsan as placeholder.
551+
// TODO: replace "libsycl-tsan" with "libsycl-tsan-dg2" when DG2
552+
// AOT support is added.
553+
"libsycl-tsan", "libsycl-tsan-pvc"};
554+
555+
if (SanitizeVal == "address")
556+
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
557+
else if (SanitizeVal == "memory")
558+
addSingleLibrary(SYCLDeviceMsanLibs[sanitizer_lib_idx]);
559+
else if (SanitizeVal == "thread")
560+
addSingleLibrary(SYCLDeviceTsanLibs[sanitizer_lib_idx]);
561+
}
562+
#endif
563+
429564
SmallVector<std::string, 8>
430565
SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
431566
bool IsSpirvAOT) {
@@ -551,30 +686,6 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
551686
{"libsycl-itt-user-wrappers", "internal"},
552687
{"libsycl-itt-compiler-wrappers", "internal"},
553688
{"libsycl-itt-stubs", "internal"}};
554-
#if !defined(_WIN32)
555-
const SYCLDeviceLibsList SYCLDeviceAsanLibs = {
556-
{"libsycl-asan", "internal"},
557-
{"libsycl-asan-cpu", "internal"},
558-
{"libsycl-asan-dg2", "internal"},
559-
{"libsycl-asan-pvc", "internal"}};
560-
const SYCLDeviceLibsList SYCLDeviceMsanLibs = {
561-
{"libsycl-msan", "internal"},
562-
{"libsycl-msan-cpu", "internal"},
563-
// Currently, we only provide aot msan libdevice for PVC and CPU.
564-
// For DG2, we just use libsycl-msan as placeholder.
565-
{"libsycl-msan", "internal"},
566-
{"libsycl-msan-pvc", "internal"}};
567-
const SYCLDeviceLibsList SYCLDeviceTsanLibs = {
568-
{"libsycl-tsan", "internal"},
569-
{"libsycl-tsan-cpu", "internal"},
570-
// Currently, we only provide aot tsan libdevice for PVC and CPU.
571-
// For DG2, we just use libsycl-tsan as placeholder.
572-
// TODO: replace "libsycl-tsan" with "libsycl-tsan-dg2" when DG2
573-
// AOT support is added.
574-
{"libsycl-tsan", "internal"},
575-
{"libsycl-tsan-pvc", "internal"}};
576-
#endif
577-
578689
const SYCLDeviceLibsList SYCLNativeCpuDeviceLibs = {
579690
{"libsycl-nativecpu_utils", "internal"}};
580691

@@ -616,119 +727,11 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
616727
options::OPT_fno_sycl_instrument_device_code, true))
617728
addLibraries(SYCLDeviceAnnotationLibs);
618729

730+
// Currently, device sanitizer support is required by some developers on
731+
// Linux platform only, so compiler only provides device sanitizer libraries
732+
// on Linux platform.
619733
#if !defined(_WIN32)
620-
621-
auto addSingleLibrary = [&](const DeviceLibOptInfo &Lib) {
622-
if (!DeviceLibLinkInfo[Lib.DeviceLibOption])
623-
return;
624-
SmallString<128> LibName(Lib.DeviceLibName);
625-
llvm::sys::path::replace_extension(LibName, LibSuffix);
626-
LibraryList.push_back(Args.MakeArgString(LibName));
627-
};
628-
629-
// This function is used to check whether there is only one GPU device
630-
// (PVC or DG2) specified in AOT compilation mode. If yes, we can use
631-
// corresponding libsycl-asan-* to improve device sanitizer performance,
632-
// otherwise stick to fallback device sanitizer library used in JIT mode.
633-
auto getSpecificGPUTarget = [](const ArgStringList &CmdArgs) -> size_t {
634-
std::string DeviceArg = getDeviceArg(CmdArgs);
635-
if ((DeviceArg.empty()) || (DeviceArg.find(",") != std::string::npos))
636-
return JIT;
637-
638-
std::string Temp;
639-
if (checkPVCDevice(DeviceArg, Temp))
640-
return AOT_PVC;
641-
642-
if (DeviceArg == "dg2")
643-
return AOT_DG2;
644-
645-
return JIT;
646-
};
647-
648-
auto getSingleBuildTarget = [&]() -> size_t {
649-
if (!IsSpirvAOT)
650-
return JIT;
651-
652-
llvm::opt::Arg *SYCLTarget = Args.getLastArg(options::OPT_fsycl_targets_EQ);
653-
if (!SYCLTarget || (SYCLTarget->getValues().size() != 1))
654-
return JIT;
655-
656-
StringRef SYCLTargetStr = SYCLTarget->getValue();
657-
if (SYCLTargetStr.starts_with("spir64_x86_64"))
658-
return AOT_CPU;
659-
660-
if (SYCLTargetStr == "intel_gpu_pvc")
661-
return AOT_PVC;
662-
663-
if (SYCLTargetStr.starts_with("intel_gpu_dg2"))
664-
return AOT_DG2;
665-
666-
if (SYCLTargetStr.starts_with("spir64_gen")) {
667-
ArgStringList TargArgs;
668-
Args.AddAllArgValues(TargArgs, options::OPT_Xs, options::OPT_Xs_separate);
669-
Args.AddAllArgValues(TargArgs, options::OPT_Xsycl_backend);
670-
llvm::opt::Arg *A = nullptr;
671-
if ((A = Args.getLastArg(options::OPT_Xsycl_backend_EQ)) &&
672-
StringRef(A->getValue()).starts_with("spir64_gen"))
673-
TargArgs.push_back(A->getValue(1));
674-
675-
return getSpecificGPUTarget(TargArgs);
676-
}
677-
678-
return JIT;
679-
};
680-
681-
std::string SanitizeVal;
682-
size_t sanitizer_lib_idx = getSingleBuildTarget();
683-
if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ,
684-
options::OPT_fno_sanitize_EQ)) {
685-
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
686-
A->getValues().size() == 1) {
687-
SanitizeVal = A->getValue();
688-
}
689-
} else {
690-
// User can pass -fsanitize=address to device compiler via
691-
// -Xsycl-target-frontend, sanitize device library must be
692-
// linked with user's device image if so.
693-
std::vector<std::string> EnabledDeviceSanitizers;
694-
695-
// NOTE: "-fsanitize=" applies to all device targets
696-
auto SyclFEArgVals = Args.getAllArgValues(options::OPT_Xsycl_frontend);
697-
auto SyclFEEQArgVals = Args.getAllArgValues(options::OPT_Xsycl_frontend_EQ);
698-
auto ArchDeviceVals = Args.getAllArgValues(options::OPT_Xarch_device);
699-
700-
std::vector<std::string> ArgVals(
701-
SyclFEArgVals.size() + SyclFEEQArgVals.size() + ArchDeviceVals.size());
702-
ArgVals.insert(ArgVals.end(), SyclFEArgVals.begin(), SyclFEArgVals.end());
703-
ArgVals.insert(ArgVals.end(), SyclFEEQArgVals.begin(),
704-
SyclFEEQArgVals.end());
705-
ArgVals.insert(ArgVals.end(), ArchDeviceVals.begin(), ArchDeviceVals.end());
706-
707-
// Driver will report error if more than one of address sanitizer, memory
708-
// sanitizer or thread sanitizer is enabled, so we only need to check first
709-
// one here.
710-
for (const std::string &Arg : ArgVals) {
711-
if (Arg.find("-fsanitize=address") != std::string::npos) {
712-
SanitizeVal = "address";
713-
break;
714-
}
715-
if (Arg.find("-fsanitize=memory") != std::string::npos) {
716-
SanitizeVal = "memory";
717-
break;
718-
}
719-
if (Arg.find("-fsanitize=thread") != std::string::npos) {
720-
SanitizeVal = "thread";
721-
break;
722-
}
723-
}
724-
}
725-
726-
if (SanitizeVal == "address")
727-
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
728-
else if (SanitizeVal == "memory")
729-
addSingleLibrary(SYCLDeviceMsanLibs[sanitizer_lib_idx]);
730-
else if (SanitizeVal == "thread")
731-
addSingleLibrary(SYCLDeviceTsanLibs[sanitizer_lib_idx]);
734+
addSYCLDeviceSanitizerLibs(C, IsSpirvAOT, LibSuffix, LibraryList);
732735
#endif
733736

734737
if (TargetTriple.isNativeCPU())

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,12 +1258,19 @@ constructFreeFunctionKernelName(const FunctionDecl *FreeFunc,
12581258
MC.mangleName(FreeFunc, Out);
12591259
std::string MangledName(Out.str());
12601260
size_t StartNums = MangledName.find_first_of("0123456789");
1261-
size_t EndNums = MangledName.find_first_not_of("0123456789", StartNums);
1262-
size_t NameLength =
1263-
std::stoi(MangledName.substr(StartNums, EndNums - StartNums));
1264-
size_t NewNameLength = 14 /*length of __sycl_kernel_*/ + NameLength;
1265-
NewName = MangledName.substr(0, StartNums) + std::to_string(NewNameLength) +
1266-
"__sycl_kernel_" + MangledName.substr(EndNums);
1261+
if (StartNums == std::string::npos) {
1262+
// Microsoft mangling name has template like ?FunctionName@@YAXH@Z
1263+
NewName =
1264+
MangledName.substr(0, 1) + "sycl_kernel_" + MangledName.substr(1);
1265+
} else {
1266+
size_t EndNums = MangledName.find_first_not_of("0123456789", StartNums);
1267+
size_t NameLength =
1268+
std::stoi(MangledName.substr(StartNums, EndNums - StartNums));
1269+
size_t NewNameLength = 14 /*length of __sycl_kernel_*/ + NameLength;
1270+
NewName = MangledName.substr(0, StartNums) +
1271+
std::to_string(NewNameLength) + "__sycl_kernel_" +
1272+
MangledName.substr(EndNums);
1273+
}
12671274
}
12681275
StableName = NewName;
12691276
return {NewName, StableName};
@@ -1932,6 +1939,10 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
19321939
// class is entered.
19331940
int StructBaseDepth = -1;
19341941

1942+
// Used to track FunctionDecl location in case if it is not available directly
1943+
// from method
1944+
SourceLocation FreeFunctionLoc;
1945+
19351946
// Check whether the object should be disallowed from being copied to kernel.
19361947
// Return true if not copyable, false if copyable.
19371948
bool checkNotCopyableToKernel(const FieldDecl *FD, QualType FieldTy) {
@@ -2045,8 +2056,13 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
20452056
}
20462057

20472058
public:
2048-
SyclKernelFieldChecker(SemaSYCL &S)
2049-
: SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
2059+
/// Constructor for the SyclKernelFieldChecker
2060+
/// \param S The SemaSYCL reference used for diagnostics and context.
2061+
/// \param FFLoc Free function location, used to report diagnostics
2062+
explicit SyclKernelFieldChecker(SemaSYCL &S,
2063+
SourceLocation FFLoc = SourceLocation())
2064+
: SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()),
2065+
FreeFunctionLoc(FFLoc) {}
20502066
static constexpr const bool VisitNthArrayElement = false;
20512067
bool isValid() { return !IsInvalid; }
20522068

@@ -2206,10 +2222,20 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
22062222
return true;
22072223
}
22082224

2209-
bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
2225+
bool leaveStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &B,
22102226
QualType) final {
22112227
--StructBaseDepth;
2212-
return true;
2228+
// FreeFunctionLoc.isInvalid() shows if checker object was created for a
2229+
// free function. If that is the case, point to the free function
2230+
// declaration.
2231+
if (B.isVirtual()) {
2232+
Diag.Report(FreeFunctionLoc.isInvalid() ? RD->getLocation()
2233+
: FreeFunctionLoc,
2234+
diag::err_sycl_kernel_virtual_arg)
2235+
<< RD->getNameAsString() << B.getType().getAsString();
2236+
IsInvalid = true;
2237+
}
2238+
return isValid();
22132239
}
22142240
};
22152241

@@ -5900,7 +5926,7 @@ void SemaSYCL::ProcessFreeFunction(FunctionDecl *FD) {
59005926
FreeFunctionDeclarations.erase(FD->getCanonicalDecl());
59015927

59025928
SyclKernelDecompMarker DecompMarker(*this);
5903-
SyclKernelFieldChecker FieldChecker(*this);
5929+
SyclKernelFieldChecker FieldChecker(*this, FD->getLocation());
59045930
SyclKernelUnionChecker UnionChecker(*this);
59055931

59065932
KernelObjVisitor Visitor{*this};

0 commit comments

Comments
 (0)