Skip to content

Commit aeb53f7

Browse files
author
iclsrc
committed
Merge from 'sycl' to 'sycl-web'
2 parents 58eed9d + 76ec3f0 commit aeb53f7

File tree

123 files changed

+5787
-1138
lines changed

Some content is hidden

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

123 files changed

+5787
-1138
lines changed

.github/workflows/scorecard.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# by a third-party and are governed by separate terms of service, privacy
33
# policy, and support documentation.
44

5-
# Check current LLVM-Project results here: https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project
5+
# Check current LLVM-Project results here: https://securityscorecards.dev/viewer/?uri=github.com/intel/llvm
66

77
name: Scorecard supply-chain security
88
on:
@@ -12,7 +12,7 @@ on:
1212
# To guarantee Maintained check is occasionally updated. See
1313
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
1414
schedule:
15-
- cron: '38 20 * * *'
15+
- cron: '30 20 * * *'
1616

1717
# Declare default permissions as read only.
1818
permissions:
@@ -22,7 +22,7 @@ jobs:
2222
analysis:
2323
name: Scorecard analysis
2424
runs-on: ubuntu-latest
25-
if: github.repository == 'llvm/llvm-project'
25+
if: github.repository == 'intel/llvm'
2626
permissions:
2727
# Needed to upload the results to code-scanning dashboard.
2828
security-events: write

.github/workflows/sycl-linux-precommit.yml

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,21 +109,37 @@ jobs:
109109
fail-fast: false
110110
matrix:
111111
include:
112-
- name: Perf tests on Intel GEN12 Graphics system
112+
- name: Intel GEN12 Graphics system
113113
runner: '["Linux", "gen12"]'
114-
- name: Perf tests on Intel Arc A-Series Graphics system
114+
image: ghcr.io/intel/llvm/ubuntu2204_intel_drivers:latest
115+
image_extra_opts: --device=/dev/dri
116+
reset_gpu: true
117+
- name: Intel Arc A-Series Graphics system
115118
runner: '["Linux", "arc"]'
119+
image: ghcr.io/intel/llvm/ubuntu2204_intel_drivers:latest
120+
image_extra_opts: --device=/dev/dri
121+
reset_gpu: true
122+
- name: AMD system
123+
runner: '["Linux", "amdgpu"]'
124+
image: ghcr.io/intel/llvm/ubuntu2204_build:latest
125+
image_extra_opts: --device=/dev/dri --device=/dev/kfd
126+
extra_cmake_args: -DHIP_PLATFORM="AMD" -DAMD_ARCH="gfx1031"
127+
- name: CUDA system
128+
runner: '["Linux", "cuda"]'
129+
image: ghcr.io/intel/llvm/ubuntu2204_build:latest
130+
image_extra_opts: --gpus all
116131
uses: ./.github/workflows/sycl-linux-run-tests.yml
117132
with:
118-
name: ${{ matrix.name }}
133+
name: Perf tests on ${{ matrix.name }}
119134
runner: ${{ matrix. runner }}
120-
image: ghcr.io/intel/llvm/ubuntu2204_intel_drivers:latest
121-
image_options: -u 1001 --device=/dev/dri --privileged --cap-add SYS_ADMIN
135+
image: ${{ matrix.image }}
136+
image_options: -u 1001 --privileged --cap-add SYS_ADMIN ${{ matrix.image_extra_opts }}
122137
target_devices: all
123-
reset_gpu: true
138+
reset_gpu: ${{ matrix.reset_gpu }}
124139

125140
env: '{"LIT_FILTER":"PerformanceTests/"}'
126141
extra_lit_opts: -a -j 1 --param enable-perf-tests=True
142+
extra_cmake_args: ${{ matrix.extra_cmake_args }}
127143

128144
ref: ${{ github.sha }}
129145
merge_ref: ''

.github/workflows/sycl-linux-run-tests.yml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ on:
8181
- '["Linux", "gen12"]'
8282
- '["amdgpu"]'
8383
- '["Linux", "arc"]'
84+
- '["cts-cpu"]'
8485
image:
8586
description: |
8687
Use option ending with ":build" for AMDGPU, ":latest" for the rest.
@@ -286,10 +287,27 @@ jobs:
286287
-DDPCPP_INSTALL_DIR="$$(dirname (which clang++))/.." \
287288
$CMAKE_EXTRA_ARGS
288289
ninja -C build-cts
290+
291+
- name: SYCL CTS List devices
292+
if: inputs.tests_selector == 'cts'
293+
run: |
294+
./build-cts/bin/test_all --list-devices
295+
289296
- name: Run SYCL CTS tests
290297
if: inputs.tests_selector == 'cts'
291298
env:
292299
ONEAPI_DEVICE_SELECTOR: ${{ inputs.target_devices }}
300+
# FIXME: For some reason the "sub_group api" test-case is failing with
301+
# SIGSEGV while running test_all, so running each binary separately.
302+
# BTW test_all requires a lot of resources to build it, so probably it'll
303+
# be better to build each binary also separately.
304+
# run: |
305+
# ./build-cts/bin/test_all $CTS_TEST_ARGS
293306
run: |
294-
./build-cts/bin/test_all --list-devices
295-
./build-cts/bin/test_all $CTS_TEST_ARGS
307+
for i in `ls -1 ./build-cts/bin`; do
308+
if [ "$i" != "test_all" ]; then
309+
echo "::group::Running $i"
310+
build-cts/bin/$i
311+
echo "::endgroup::"
312+
fi
313+
done

.github/workflows/sycl-nightly.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,21 @@ jobs:
7171
image: ghcr.io/intel/llvm/ubuntu2204_build:latest
7272
image_options: -u 1001 --gpus all --cap-add SYS_ADMIN
7373
target_devices: ext_oneapi_cuda:gpu
74+
75+
- name: SYCL-CTS
76+
runner: '["cts-cpu"]'
77+
image: ghcr.io/intel/llvm/ubuntu2204_intel_drivers:latest
78+
image_options: -u 1001 --device=/dev/dri --privileged --cap-add SYS_ADMIN
79+
target_devices: opencl:cpu
80+
tests_selector: cts
7481
uses: ./.github/workflows/sycl-linux-run-tests.yml
7582
with:
7683
name: ${{ matrix.name }}
7784
runner: ${{ matrix.runner }}
7885
image: ${{ matrix.image }}
7986
image_options: ${{ matrix.image_options }}
8087
target_devices: ${{ matrix.target_devices }}
88+
tests_selector: ${{ matrix.tests_selector }}
8189
reset_gpu: ${{ matrix.reset_gpu }}
8290
ref: ${{ github.sha }}
8391
merge_ref: ''

clang/lib/CodeGen/CGVTT.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
4242
llvm::GlobalVariable::LinkageTypes Linkage,
4343
const CXXRecordDecl *RD) {
4444
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
45-
llvm::ArrayType *ArrayType =
46-
llvm::ArrayType::get(CGM.DefaultInt8PtrTy, Builder.getVTTComponents().size());
45+
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
46+
CGM.GlobalsInt8PtrTy, Builder.getVTTComponents().size());
4747

4848
SmallVector<llvm::GlobalVariable *, 8> VTables;
4949
SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
@@ -81,9 +81,6 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
8181
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true,
8282
/*InRangeIndex=*/1);
8383

84-
Init = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
85-
Init, CGM.Int8PtrTy);
86-
8784
VTTComponents.push_back(Init);
8885
}
8986

@@ -117,9 +114,9 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
117114

118115
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
119116

120-
llvm::ArrayType *ArrayType =
121-
llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
122-
llvm::Align Align = CGM.getDataLayout().getABITypeAlign(CGM.Int8PtrTy);
117+
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
118+
CGM.GlobalsInt8PtrTy, Builder.getVTTComponents().size());
119+
llvm::Align Align = CGM.getDataLayout().getABITypeAlign(CGM.GlobalsInt8PtrTy);
123120

124121
llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
125122
Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align);

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ bool CodeGenVTables::useRelativeLayout() const {
692692
llvm::Type *CodeGenModule::getVTableComponentType() const {
693693
if (UseRelativeLayout(*this))
694694
return Int32Ty;
695-
return Int8PtrTy;
695+
return GlobalsInt8PtrTy;
696696
}
697697

698698
llvm::Type *CodeGenVTables::getVTableComponentType() const {
@@ -704,7 +704,7 @@ static void AddPointerLayoutOffset(const CodeGenModule &CGM,
704704
CharUnits offset) {
705705
builder.add(llvm::ConstantExpr::getIntToPtr(
706706
llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()),
707-
CGM.Int8PtrTy));
707+
CGM.GlobalsInt8PtrTy));
708708
}
709709

710710
static void AddRelativeLayoutOffset(const CodeGenModule &CGM,
@@ -741,7 +741,7 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
741741
vtableHasLocalLinkage,
742742
/*isCompleteDtor=*/false);
743743
else
744-
return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy));
744+
return builder.add(rtti);
745745

746746
case VTableComponent::CK_FunctionPointer:
747747
case VTableComponent::CK_CompleteDtorPointer:
@@ -760,7 +760,8 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
760760
? MD->hasAttr<CUDADeviceAttr>()
761761
: (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>());
762762
if (!CanEmitMethod)
763-
return builder.add(llvm::ConstantExpr::getNullValue(CGM.Int8PtrTy));
763+
return builder.add(
764+
llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
764765
// Method is acceptable, continue processing as usual.
765766
}
766767

@@ -773,20 +774,20 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
773774
// with the local symbol. As a temporary solution, fill these components
774775
// with zero. We shouldn't be calling these in the first place anyway.
775776
if (useRelativeLayout())
776-
return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
777+
return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
777778

778779
// For NVPTX devices in OpenMP emit special functon as null pointers,
779780
// otherwise linking ends up with unresolved references.
780781
if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
781782
CGM.getTriple().isNVPTX())
782-
return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
783+
return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
783784
llvm::FunctionType *fnTy =
784785
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
785786
llvm::Constant *fn = cast<llvm::Constant>(
786787
CGM.CreateRuntimeFunction(fnTy, name).getCallee());
787788
if (auto f = dyn_cast<llvm::Function>(fn))
788789
f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
789-
return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy);
790+
return fn;
790791
};
791792

792793
llvm::Constant *fnPtr;
@@ -824,15 +825,26 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
824825
return addRelativeComponent(
825826
builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
826827
component.getKind() == VTableComponent::CK_CompleteDtorPointer);
827-
} else
828-
return builder.add(llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy));
828+
} else {
829+
// TODO: this icky and only exists due to functions being in the generic
830+
// address space, rather than the global one, even though they are
831+
// globals; fixing said issue might be intrusive, and will be done
832+
// later.
833+
unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
834+
unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
835+
836+
if (FnAS != GVAS)
837+
fnPtr =
838+
llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
839+
return builder.add(fnPtr);
840+
}
829841
}
830842

831843
case VTableComponent::CK_UnusedFunctionPointer:
832844
if (useRelativeLayout())
833845
return builder.add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
834846
else
835-
return builder.addNullPointer(CGM.Int8PtrTy);
847+
return builder.addNullPointer(CGM.GlobalsInt8PtrTy);
836848
}
837849

838850
llvm_unreachable("Unexpected vtable component kind");

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7977,7 +7977,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
79777977
// FIXME: should we even be calling this method if RTTI is disabled
79787978
// and it's not for EH?
79797979
if (!shouldEmitRTTI(ForEH))
7980-
return llvm::Constant::getNullValue(Int8PtrTy);
7980+
return llvm::Constant::getNullValue(GlobalsInt8PtrTy);
79817981

79827982
if (ForEH && Ty->isObjCObjectPointerType() &&
79837983
LangOpts.ObjCRuntime.isGNUFamily())

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
670670
CGF.EmitBlock(FnVirtual);
671671

672672
// Cast the adjusted this to a pointer to vtable pointer and load.
673-
llvm::Type *VTableTy = Builder.getInt8PtrTy();
673+
llvm::Type *VTableTy = CGF.CGM.GlobalsInt8PtrTy;
674674
CharUnits VTablePtrAlign =
675675
CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
676676
CGF.getPointerAlign());
@@ -1942,11 +1942,11 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
19421942
/// Load the VTT.
19431943
llvm::Value *VTT = CGF.LoadCXXVTT();
19441944
if (VirtualPointerIndex)
1945-
VTT = CGF.Builder.CreateConstInBoundsGEP1_64(
1946-
CGF.VoidPtrTy, VTT, VirtualPointerIndex);
1945+
VTT = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.GlobalsVoidPtrTy, VTT,
1946+
VirtualPointerIndex);
19471947

19481948
// And load the address point from the VTT.
1949-
return CGF.Builder.CreateAlignedLoad(CGF.VoidPtrTy, VTT,
1949+
return CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
19501950
CGF.getPointerAlign());
19511951
}
19521952

@@ -1974,12 +1974,13 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
19741974
CGM.getItaniumVTableContext().getVTableLayout(RD);
19751975
llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
19761976

1977-
// Use pointer alignment for the vtable. Otherwise we would align them based
1978-
// on the size of the initializer which doesn't make sense as only single
1979-
// values are read.
1977+
// Use pointer to global alignment for the vtable. Otherwise we would align
1978+
// them based on the size of the initializer which doesn't make sense as only
1979+
// single values are read.
1980+
LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
19801981
unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
19811982
? 32
1982-
: CGM.getTarget().getPointerAlign(LangAS::Default);
1983+
: CGM.getTarget().getPointerAlign(AS);
19831984

19841985
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
19851986
Name, VTableType, llvm::GlobalValue::ExternalLinkage,
@@ -3281,10 +3282,9 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
32813282
// Note for the future: If we would ever like to do deferred emission of
32823283
// RTTI, check if emitting vtables opportunistically need any adjustment.
32833284

3284-
GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
3285-
/*isConstant=*/true,
3286-
llvm::GlobalValue::ExternalLinkage, nullptr,
3287-
Name);
3285+
GV = new llvm::GlobalVariable(
3286+
CGM.getModule(), CGM.GlobalsInt8PtrTy,
3287+
/*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);
32883288
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
32893289
CGM.setGVProperties(GV, RD);
32903290
// Import the typeinfo symbol when all non-inline virtual methods are
@@ -3680,8 +3680,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
36803680
if (CGM.getItaniumVTableContext().isRelativeLayout())
36813681
VTable = CGM.getModule().getNamedAlias(VTableName);
36823682
if (!VTable) {
3683-
llvm::Type *Ty = llvm::ArrayType::get(CGM.DefaultInt8PtrTy, 0);
3684-
VTable = CGM.CreateRuntimeVariable(Ty, VTableName);
3683+
llvm::Type *Ty = llvm::ArrayType::get(CGM.GlobalsInt8PtrTy, 0);
3684+
VTable = CGM.getModule().getOrInsertGlobal(VTableName, Ty);
36853685
}
36863686

36873687
CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
@@ -3698,7 +3698,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
36983698
llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
36993699
} else {
37003700
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3701-
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.DefaultInt8PtrTy,
3701+
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
37023702
VTable, Two);
37033703
}
37043704

@@ -3835,7 +3835,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
38353835
llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
38363836
TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
38373837
TypeNameField =
3838-
llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy);
3838+
llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);
38393839
} else {
38403840
TypeNameField = TypeName;
38413841
}
@@ -3965,7 +3965,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
39653965
GV->setComdat(M.getOrInsertComdat(GV->getName()));
39663966

39673967
CharUnits Align = CGM.getContext().toCharUnitsFromBits(
3968-
CGM.getTarget().getPointerAlign(LangAS::Default));
3968+
CGM.getTarget().getPointerAlign(CGM.GetGlobalVarAddressSpace(nullptr)));
39693969
GV->setAlignment(Align.getAsAlign());
39703970

39713971
// The Itanium ABI specifies that type_info objects must be globally

clang/lib/Driver/ToolChains/MSVC.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,23 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
130130
CmdArgs.push_back("-defaultlib:oldnames");
131131
}
132132

133-
if ((!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_fsycl) &&
133+
if ((Args.hasArg(options::OPT_fsycl) &&
134134
!Args.hasArg(options::OPT_nolibsycl)) ||
135135
Args.hasArg(options::OPT_fsycl_host_compiler_EQ)) {
136136
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
137137
TC.getDriver().Dir + "/../lib"));
138-
// When msvcrtd is added via --dependent-lib, we add the sycld
139-
// equivalent. Do not add the -defaultlib as it conflicts.
140-
if (!isDependentLibAdded(Args, "msvcrtd")) {
138+
if (!Args.hasArg(options::OPT__SLASH_MDd) &&
139+
!isDependentLibAdded(Args, "msvcrtd")) {
141140
if (Args.hasArg(options::OPT_fpreview_breaking_changes))
142141
CmdArgs.push_back("-defaultlib:sycl" SYCL_MAJOR_VERSION "-preview.lib");
143142
else
144143
CmdArgs.push_back("-defaultlib:sycl" SYCL_MAJOR_VERSION ".lib");
144+
} else {
145+
if (Args.hasArg(options::OPT_fpreview_breaking_changes))
146+
CmdArgs.push_back("-defaultlib:sycl" SYCL_MAJOR_VERSION
147+
"-previewd.lib");
148+
else
149+
CmdArgs.push_back("-defaultlib:sycl" SYCL_MAJOR_VERSION "d.lib");
145150
}
146151
CmdArgs.push_back("-defaultlib:sycl-devicelib-host.lib");
147152
}

clang/test/CodeGenCXX/dynamic-cast-address-space.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// XFAIL: *
2-
//
31
// RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s
42
struct A { virtual void f(); };
53
struct B : A { };

0 commit comments

Comments
 (0)