2013-03-22 06:34:35 +00:00
|
|
|
//===--- DeclOpenMP.cpp - Declaration OpenMP AST Node Implementation ------===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-03-22 06:34:35 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
2018-05-09 01:00:01 +00:00
|
|
|
/// This file implements OMPThreadPrivateDecl, OMPCapturedExprDecl
|
2016-02-08 09:29:13 +00:00
|
|
|
/// classes.
|
2013-03-22 06:34:35 +00:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
2014-01-07 11:51:46 +00:00
|
|
|
#include "clang/AST/DeclBase.h"
|
2013-03-22 06:34:35 +00:00
|
|
|
#include "clang/AST/DeclOpenMP.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OMPThreadPrivateDecl Implementation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
void OMPThreadPrivateDecl::anchor() {}
|
2013-03-22 06:34:35 +00:00
|
|
|
|
|
|
|
OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
2013-05-13 04:18:18 +00:00
|
|
|
ArrayRef<Expr *> VL) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
auto *D = OMPDeclarativeDirective::createDirective<OMPThreadPrivateDecl>(
|
2024-10-24 10:23:40 +01:00
|
|
|
C, DC, {}, VL.size(), L);
|
2013-03-22 06:34:35 +00:00
|
|
|
D->setVars(VL);
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2024-04-25 11:43:13 +08:00
|
|
|
OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
GlobalDeclID ID,
|
|
|
|
unsigned N) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
return OMPDeclarativeDirective::createEmptyDirective<OMPThreadPrivateDecl>(
|
|
|
|
C, ID, 0, N);
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
|
|
|
|
2013-05-13 04:18:18 +00:00
|
|
|
void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
assert(VL.size() == Data->getNumChildren() &&
|
2013-03-22 06:34:35 +00:00
|
|
|
"Number of variables is not the same as the preallocated buffer");
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
llvm::copy(VL, getVars().begin());
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
|
2019-03-07 17:54:44 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OMPAllocateDecl Implementation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void OMPAllocateDecl::anchor() { }
|
|
|
|
|
|
|
|
OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
|
2019-03-12 18:52:33 +00:00
|
|
|
SourceLocation L, ArrayRef<Expr *> VL,
|
|
|
|
ArrayRef<OMPClause *> CL) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
auto *D = OMPDeclarativeDirective::createDirective<OMPAllocateDecl>(
|
|
|
|
C, DC, CL, VL.size(), L);
|
2019-03-07 17:54:44 +00:00
|
|
|
D->setVars(VL);
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2024-04-25 11:43:13 +08:00
|
|
|
OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
GlobalDeclID ID,
|
2019-03-12 18:52:33 +00:00
|
|
|
unsigned NVars,
|
|
|
|
unsigned NClauses) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
return OMPDeclarativeDirective::createEmptyDirective<OMPAllocateDecl>(
|
|
|
|
C, ID, NClauses, NVars, SourceLocation());
|
2019-03-07 17:54:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OMPAllocateDecl::setVars(ArrayRef<Expr *> VL) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
assert(VL.size() == Data->getNumChildren() &&
|
2019-03-07 17:54:44 +00:00
|
|
|
"Number of variables is not the same as the preallocated buffer");
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
llvm::copy(VL, getVars().begin());
|
2019-03-12 18:52:33 +00:00
|
|
|
}
|
|
|
|
|
2018-09-26 04:28:39 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OMPRequiresDecl Implementation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void OMPRequiresDecl::anchor() {}
|
|
|
|
|
|
|
|
OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
ArrayRef<OMPClause *> CL) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
return OMPDeclarativeDirective::createDirective<OMPRequiresDecl>(C, DC, CL, 0,
|
|
|
|
L);
|
2018-09-26 04:28:39 +00:00
|
|
|
}
|
|
|
|
|
2024-04-25 11:43:13 +08:00
|
|
|
OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
GlobalDeclID ID,
|
2018-09-26 04:28:39 +00:00
|
|
|
unsigned N) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
return OMPDeclarativeDirective::createEmptyDirective<OMPRequiresDecl>(
|
|
|
|
C, ID, N, 0, SourceLocation());
|
2018-09-26 04:28:39 +00:00
|
|
|
}
|
|
|
|
|
2016-03-03 05:21:39 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OMPDeclareReductionDecl Implementation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-01 21:16:54 +00:00
|
|
|
OMPDeclareReductionDecl::OMPDeclareReductionDecl(
|
|
|
|
Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
|
|
QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope)
|
|
|
|
: ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr),
|
|
|
|
PrevDeclInScope(PrevDeclInScope) {
|
2023-11-01 12:39:33 +03:00
|
|
|
setInitializer(nullptr, OMPDeclareReductionInitKind::Call);
|
2018-08-01 21:16:54 +00:00
|
|
|
}
|
|
|
|
|
2016-03-03 05:21:39 +00:00
|
|
|
void OMPDeclareReductionDecl::anchor() {}
|
|
|
|
|
|
|
|
OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create(
|
|
|
|
ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
|
|
QualType T, OMPDeclareReductionDecl *PrevDeclInScope) {
|
|
|
|
return new (C, DC) OMPDeclareReductionDecl(OMPDeclareReduction, DC, L, Name,
|
|
|
|
T, PrevDeclInScope);
|
|
|
|
}
|
|
|
|
|
|
|
|
OMPDeclareReductionDecl *
|
2024-04-25 11:43:13 +08:00
|
|
|
OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
2016-03-03 05:21:39 +00:00
|
|
|
return new (C, ID) OMPDeclareReductionDecl(
|
|
|
|
OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(),
|
|
|
|
QualType(), /*PrevDeclInScope=*/nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
OMPDeclareReductionDecl *OMPDeclareReductionDecl::getPrevDeclInScope() {
|
|
|
|
return cast_or_null<OMPDeclareReductionDecl>(
|
|
|
|
PrevDeclInScope.get(getASTContext().getExternalSource()));
|
|
|
|
}
|
|
|
|
const OMPDeclareReductionDecl *
|
|
|
|
OMPDeclareReductionDecl::getPrevDeclInScope() const {
|
|
|
|
return cast_or_null<OMPDeclareReductionDecl>(
|
|
|
|
PrevDeclInScope.get(getASTContext().getExternalSource()));
|
|
|
|
}
|
|
|
|
|
2016-02-08 09:29:13 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-02-01 20:25:04 +00:00
|
|
|
// OMPDeclareMapperDecl Implementation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void OMPDeclareMapperDecl::anchor() {}
|
|
|
|
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create(
|
|
|
|
ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
|
|
QualType T, DeclarationName VarName, ArrayRef<OMPClause *> Clauses,
|
|
|
|
OMPDeclareMapperDecl *PrevDeclInScope) {
|
|
|
|
return OMPDeclarativeDirective::createDirective<OMPDeclareMapperDecl>(
|
|
|
|
C, DC, Clauses, 1, L, Name, T, VarName, PrevDeclInScope);
|
2019-02-01 20:25:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-25 11:43:13 +08:00
|
|
|
OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
GlobalDeclID ID,
|
|
|
|
unsigned N) {
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
return OMPDeclarativeDirective::createEmptyDirective<OMPDeclareMapperDecl>(
|
|
|
|
C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(),
|
|
|
|
DeclarationName(), /*PrevDeclInScope=*/nullptr);
|
2019-02-01 20:25:04 +00:00
|
|
|
}
|
|
|
|
|
2019-02-01 21:19:20 +00:00
|
|
|
OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() {
|
|
|
|
return cast_or_null<OMPDeclareMapperDecl>(
|
|
|
|
PrevDeclInScope.get(getASTContext().getExternalSource()));
|
|
|
|
}
|
|
|
|
|
|
|
|
const OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() const {
|
|
|
|
return cast_or_null<OMPDeclareMapperDecl>(
|
|
|
|
PrevDeclInScope.get(getASTContext().getExternalSource()));
|
|
|
|
}
|
|
|
|
|
2019-02-01 20:25:04 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2016-02-11 05:35:55 +00:00
|
|
|
// OMPCapturedExprDecl Implementation.
|
2016-02-08 09:29:13 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-02-11 05:35:55 +00:00
|
|
|
void OMPCapturedExprDecl::anchor() {}
|
2016-02-08 09:29:13 +00:00
|
|
|
|
2016-02-11 05:35:55 +00:00
|
|
|
OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
|
2016-12-20 16:51:02 +00:00
|
|
|
IdentifierInfo *Id, QualType T,
|
|
|
|
SourceLocation StartLoc) {
|
2018-06-01 13:04:26 +00:00
|
|
|
return new (C, DC) OMPCapturedExprDecl(
|
|
|
|
C, DC, Id, T, C.getTrivialTypeSourceInfo(T), StartLoc);
|
2016-02-08 09:29:13 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 05:35:55 +00:00
|
|
|
OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
|
2024-04-25 11:43:13 +08:00
|
|
|
GlobalDeclID ID) {
|
2018-06-01 13:04:26 +00:00
|
|
|
return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(),
|
|
|
|
/*TInfo=*/nullptr, SourceLocation());
|
2016-02-08 09:29:13 +00:00
|
|
|
}
|
|
|
|
|
2016-12-20 16:51:02 +00:00
|
|
|
SourceRange OMPCapturedExprDecl::getSourceRange() const {
|
|
|
|
assert(hasInit());
|
2018-08-09 21:09:38 +00:00
|
|
|
return SourceRange(getInit()->getBeginLoc(), getInit()->getEndLoc());
|
2016-12-20 16:51:02 +00:00
|
|
|
}
|