Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dynamic cast leads the undefined symbol in clang/msys2/windows #1724

Merged
merged 10 commits into from
Nov 22, 2024
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
endif()
if(MINGW OR CYGWIN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Otherwise, dynamic_cast to the class marked by final will be failed.
# https://reviews.llvm.org/D154658 should be relevant
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-assume-unique-vtables")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
endif()
endif()

# For now, PGI/NVHPC nvc++ compiler doesn't seem to support
Expand Down
27 changes: 12 additions & 15 deletions common/cuda_hip/solver/batch_bicgstab_launch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "core/base/batch_struct.hpp"
#include "core/matrix/batch_struct.hpp"
#include "core/solver/batch_bicgstab_kernels.hpp"
#include "core/solver/batch_dispatch.hpp"


namespace gko {
Expand Down Expand Up @@ -50,32 +51,28 @@ void launch_apply_kernel(
device_type<_vtype>* const __restrict__ workspace_data, \
const int& block_size, const size_t& shared_size)

#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH(...) \
GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE_VARGS( \
GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, __VA_ARGS__)

#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_0_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 0, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 0, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_1_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 1, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 1, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_2_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 2, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 2, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_3_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 3, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 3, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_4_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 4, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 4, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_5_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 5, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 5, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_6_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 6, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 6, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_7_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 7, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 7, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_8_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 8, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 8, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_9_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 9, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 9, false)
#define GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH_9_TRUE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_BICGSTAB_LAUNCH, 9, true)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_BICGSTAB_LAUNCH, 9, true)


} // namespace batch_bicgstab
Expand Down
19 changes: 8 additions & 11 deletions common/cuda_hip/solver/batch_cg_launch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "core/base/batch_struct.hpp"
#include "core/matrix/batch_struct.hpp"
#include "core/solver/batch_cg_kernels.hpp"
#include "core/solver/batch_dispatch.hpp"


namespace gko {
Expand Down Expand Up @@ -50,24 +51,20 @@ void launch_apply_kernel(
device_type<_vtype>* const __restrict__ workspace_data, \
const int& block_size, const size_t& shared_size)

#define GKO_INSTANTIATE_BATCH_CG_LAUNCH(...) \
GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE_VARGS(GKO_DECLARE_BATCH_CG_LAUNCH, \
__VA_ARGS__)

#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_0_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 0, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 0, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_1_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 1, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 1, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_2_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 2, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 2, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_3_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 3, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 3, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_4_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 4, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 4, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_5_FALSE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 5, false)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 5, false)
#define GKO_INSTANTIATE_BATCH_CG_LAUNCH_5_TRUE \
GKO_BATCH_INSTANTIATE_VARGS(GKO_INSTANTIATE_BATCH_CG_LAUNCH, 5, true)
GKO_BATCH_INSTANTIATE(GKO_DECLARE_BATCH_CG_LAUNCH, 5, true)


} // namespace batch_cg
Expand Down
12 changes: 7 additions & 5 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ set(config_source
if(GINKGO_BUILD_MPI)
list(APPEND config_source config/schwarz_config.cpp)
endif()
# MSVC: To solve LNK1189, we separate the library as a workaround
# MSVC: LNK1189 issue
# CLANG in MSYS2 (MINGW): too many exported symbols
# We separate the library as a workaround to solve this issue
# To make ginkgo still be the major library, we make the original to ginkgo_core in MSVC/shared
# TODO: should think another way to solve it like dllexport or def file
set(ginkgo_core "ginkgo")
if(MSVC AND BUILD_SHARED_LIBS)
if((MSVC OR MINGW) AND BUILD_SHARED_LIBS)
set(ginkgo_core "ginkgo_core")
endif()

Expand Down Expand Up @@ -142,8 +144,8 @@ if(GINKGO_BUILD_MPI)
distributed/preconditioner/schwarz.cpp)
endif()

# MSVC/shared: make ginkgo be the major library
if(MSVC AND BUILD_SHARED_LIBS)
# MSVC or CLANG/msys2 with shared: make ginkgo be the major library
if((MSVC OR MINGW) AND BUILD_SHARED_LIBS)
add_library(ginkgo "")
target_sources(ginkgo PRIVATE ${config_source})
ginkgo_compile_features(ginkgo)
Expand All @@ -161,7 +163,7 @@ ginkgo_compile_features(${ginkgo_core})
# add a namespace alias so Ginkgo can always be included as Ginkgo::ginkgo
# regardless of whether it is installed or added as a subdirectory
add_library(Ginkgo::ginkgo ALIAS ginkgo)
if(MSVC AND BUILD_SHARED_LIBS)
if((MSVC OR MINGW) AND BUILD_SHARED_LIBS)
target_link_libraries(ginkgo PUBLIC ${ginkgo_core})
endif()
target_link_libraries(${ginkgo_core}
Expand Down
54 changes: 54 additions & 0 deletions core/base/batch_instantiation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2024 The Ginkgo authors
//
// SPDX-License-Identifier: BSD-3-Clause

#ifndef GKO_PUBLIC_CORE_BASE_BATCH_INSTANTIATION_HPP_
#define GKO_PUBLIC_CORE_BASE_BATCH_INSTANTIATION_HPP_

#include <ginkgo/core/base/types.hpp>
#include <ginkgo/core/matrix/batch_csr.hpp>
#include <ginkgo/core/matrix/batch_dense.hpp>
#include <ginkgo/core/matrix/batch_ell.hpp>
#include <ginkgo/core/matrix/batch_identity.hpp>
#include <ginkgo/core/preconditioner/batch_jacobi.hpp>


namespace gko {
namespace batch {


// just make the call list more consistent
#define GKO_CALL(_macro, ...) GKO_INDIRECT(_macro(__VA_ARGS__))

#define GKO_BATCH_INSTANTIATE_PRECONDITIONER(_next, ...) \
GKO_INDIRECT(_next(__VA_ARGS__, gko::batch::matrix::Identity)); \
GKO_INDIRECT(_next(__VA_ARGS__, gko::batch::preconditioner::Jacobi))

#define GKO_BATCH_INSTANTIATE_MATRIX(_next, ...) \
GKO_INDIRECT(_next(__VA_ARGS__, gko::batch::matrix::Ell)); \
GKO_INDIRECT(_next(__VA_ARGS__, gko::batch::matrix::Dense)); \
GKO_INDIRECT(_next(__VA_ARGS__, gko::batch::matrix::Csr))

/**
* Instantiates a template for each valid combination of value type, batch
* matrix type, and batch preconditioner type. This only allows batch matrix
* type and preconditioner type also uses the same value type.
*
* @param args the first should be a macro which expands the template
* instantiation (not including the leading `template` specifier).
* Should take three arguments, where the first is replaced by the
* value type, the second by the matrix, and the third by the
* preconditioner.
*
* @note the second and third arguments only accept the base type.s
*/
#define GKO_INSTANTIATE_FOR_BATCH_VALUE_MATRIX_PRECONDITIONER(...) \
GKO_CALL(GKO_BATCH_INSTANTIATE_MATRIX, \
GKO_BATCH_INSTANTIATE_PRECONDITIONER, \
GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE_VARGS, __VA_ARGS__)


} // namespace batch
} // namespace gko

#endif // GKO_PUBLIC_CORE_BASE_BATCH_INSTANTIATION_HPP_
16 changes: 14 additions & 2 deletions core/device_hooks/common_kernels.inc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <ginkgo/core/base/exception_helpers.hpp>
#include <ginkgo/core/base/types.hpp>

#include "core/base/batch_instantiation.hpp"
#include "core/base/batch_multi_vector_kernels.hpp"
#include "core/base/device_matrix_data_kernels.hpp"
#include "core/base/index_set_kernels.hpp"
Expand Down Expand Up @@ -168,6 +169,13 @@
_macro(ValueType, ValueTypeKrylovBases) GKO_NOT_COMPILED(GKO_HOOK_MODULE); \
GKO_INSTANTIATE_FOR_EACH_CB_GMRES_CONST_TYPE(_macro)

#define GKO_STUB_BATCH_VALUE_MATRIX_PRECONDITIONER(_declare, _wrapper) \
template <typename ValueType, typename BatchMatrixType, typename PrecType> \
_declare(ValueType, BatchMatrixType, PrecType) \
GKO_NOT_COMPILED(GKO_HOOK_MODULE); \
GKO_INSTANTIATE_FOR_BATCH_VALUE_MATRIX_PRECONDITIONER(_wrapper)


namespace gko {
namespace kernels {
namespace GKO_HOOK_MODULE {
Expand Down Expand Up @@ -421,7 +429,9 @@
namespace batch_bicgstab {


GKO_STUB_VALUE_TYPE(GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL);
GKO_STUB_BATCH_VALUE_MATRIX_PRECONDITIONER(

Check warning on line 432 in core/device_hooks/common_kernels.inc.cpp

View check run for this annotation

Codecov / codecov/patch

core/device_hooks/common_kernels.inc.cpp#L432

Added line #L432 was not covered by tests
GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL,
GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL_WRAPPER);


} // namespace batch_bicgstab
Expand All @@ -430,7 +440,9 @@
namespace batch_cg {


GKO_STUB_VALUE_TYPE(GKO_DECLARE_BATCH_CG_APPLY_KERNEL);
GKO_STUB_BATCH_VALUE_MATRIX_PRECONDITIONER(

Check warning on line 443 in core/device_hooks/common_kernels.inc.cpp

View check run for this annotation

Codecov / codecov/patch

core/device_hooks/common_kernels.inc.cpp#L443

Added line #L443 was not covered by tests
GKO_DECLARE_BATCH_CG_APPLY_KERNEL,
GKO_DECLARE_BATCH_CG_APPLY_KERNEL_WRAPPER);


} // namespace batch_cg
Expand Down
19 changes: 15 additions & 4 deletions core/solver/batch_bicgstab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@
#include <ginkgo/core/base/batch_lin_op.hpp>
#include <ginkgo/core/base/batch_multi_vector.hpp>
#include <ginkgo/core/base/math.hpp>
#include <ginkgo/core/matrix/batch_csr.hpp>
#include <ginkgo/core/matrix/batch_dense.hpp>
#include <ginkgo/core/matrix/batch_ell.hpp>
#include <ginkgo/core/matrix/batch_identity.hpp>
#include <ginkgo/core/preconditioner/batch_jacobi.hpp>

#include "core/base/batch_multi_vector_kernels.hpp"
#include "core/base/dispatch_helper.hpp"
#include "core/solver/batch_bicgstab_kernels.hpp"


Expand Down Expand Up @@ -45,14 +51,19 @@ void Bicgstab<ValueType>::solver_apply(
const MultiVector<ValueType>* b, MultiVector<ValueType>* x,
log::detail::log_data<remove_complex<ValueType>>* log_data) const
{
using MVec = MultiVector<ValueType>;
const kernels::batch_bicgstab::settings<remove_complex<ValueType>> settings{
this->max_iterations_, static_cast<real_type>(this->residual_tol_),
parameters_.tolerance_type};
auto exec = this->get_executor();
exec->run(bicgstab::make_apply(settings, this->system_matrix_.get(),
this->preconditioner_.get(), b, x,
*log_data));

run<matrix::Dense<ValueType>, matrix::Csr<ValueType>,
matrix::Ell<ValueType>>(this->system_matrix_.get(), [&](auto matrix) {
run<matrix::Identity<ValueType>, preconditioner::Jacobi<ValueType>>(
this->preconditioner_.get(), [&](auto preconditioner) {
exec->run(bicgstab::make_apply(settings, matrix, preconditioner,
b, x, *log_data));
});
});
}


Expand Down
16 changes: 11 additions & 5 deletions core/solver/batch_bicgstab_kernels.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,19 +174,25 @@ storage_config compute_shared_storage(const int available_shared_mem,
} // namespace batch_bicgstab


#define GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL(_type) \
#define GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL(_type, _matrix, _prec) \
void apply( \
std::shared_ptr<const DefaultExecutor> exec, \
const gko::kernels::batch_bicgstab::settings<remove_complex<_type>>& \
options, \
const batch::BatchLinOp* a, const batch::BatchLinOp* preconditioner, \
const _matrix* a, const _prec* preconditioner, \
const batch::MultiVector<_type>* b, batch::MultiVector<_type>* x, \
gko::batch::log::detail::log_data<remove_complex<_type>>& logdata)

#define GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL_WRAPPER(_vtype, _matrix, \
_precond) \
GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL(_vtype, _matrix<_vtype>, \
_precond<_vtype>)

#define GKO_DECLARE_ALL_AS_TEMPLATES \
template <typename ValueType> \
GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL(ValueType)

#define GKO_DECLARE_ALL_AS_TEMPLATES \
template <typename ValueType, typename BatchMatrixType, typename PrecType> \
GKO_DECLARE_BATCH_BICGSTAB_APPLY_KERNEL(ValueType, BatchMatrixType, \
PrecType)


GKO_DECLARE_FOR_ALL_EXECUTOR_NAMESPACES(batch_bicgstab,
Expand Down
20 changes: 17 additions & 3 deletions core/solver/batch_cg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
#include <ginkgo/core/base/batch_lin_op.hpp>
#include <ginkgo/core/base/batch_multi_vector.hpp>
#include <ginkgo/core/base/math.hpp>
#include <ginkgo/core/matrix/batch_csr.hpp>
#include <ginkgo/core/matrix/batch_dense.hpp>
#include <ginkgo/core/matrix/batch_ell.hpp>
#include <ginkgo/core/matrix/batch_identity.hpp>
#include <ginkgo/core/preconditioner/batch_jacobi.hpp>

#include "core/base/batch_multi_vector_kernels.hpp"
#include "core/base/dispatch_helper.hpp"
#include "core/solver/batch_cg_kernels.hpp"


namespace gko {
namespace batch {
namespace solver {
Expand Down Expand Up @@ -49,8 +54,17 @@ void Cg<ValueType>::solver_apply(
this->max_iterations_, static_cast<real_type>(this->residual_tol_),
parameters_.tolerance_type};
auto exec = this->get_executor();
exec->run(cg::make_apply(settings, this->system_matrix_.get(),
this->preconditioner_.get(), b, x, *log_data));

run<batch::matrix::Dense<ValueType>, batch::matrix::Csr<ValueType>,
batch::matrix::Ell<ValueType>>(
this->system_matrix_.get(), [&](auto matrix) {
run<batch::matrix::Identity<ValueType>,
batch::preconditioner::Jacobi<ValueType>>(
this->preconditioner_.get(), [&](auto preconditioner) {
exec->run(cg::make_apply(settings, matrix, preconditioner,
b, x, *log_data));
});
});
}


Expand Down
23 changes: 13 additions & 10 deletions core/solver/batch_cg_kernels.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,22 @@ storage_config compute_shared_storage(const int available_shared_mem,
} // namespace batch_cg


#define GKO_DECLARE_BATCH_CG_APPLY_KERNEL(_type) \
void apply( \
std::shared_ptr<const DefaultExecutor> exec, \
const gko::kernels::batch_cg::settings<remove_complex<_type>>& \
options, \
const batch::BatchLinOp* mat, const batch::BatchLinOp* preconditioner, \
const batch::MultiVector<_type>* b, batch::MultiVector<_type>* x, \
#define GKO_DECLARE_BATCH_CG_APPLY_KERNEL(_type, _matrix, _prec) \
void apply( \
std::shared_ptr<const DefaultExecutor> exec, \
const gko::kernels::batch_cg::settings<remove_complex<_type>>& \
options, \
const _matrix* mat, const _prec* preconditioner, \
const batch::MultiVector<_type>* b, batch::MultiVector<_type>* x, \
gko::batch::log::detail::log_data<remove_complex<_type>>& logdata)

#define GKO_DECLARE_BATCH_CG_APPLY_KERNEL_WRAPPER(_vtype, _matrix, _precond) \
GKO_DECLARE_BATCH_CG_APPLY_KERNEL(_vtype, _matrix<_vtype>, _precond<_vtype>)

#define GKO_DECLARE_ALL_AS_TEMPLATES \
template <typename ValueType> \
GKO_DECLARE_BATCH_CG_APPLY_KERNEL(ValueType)

#define GKO_DECLARE_ALL_AS_TEMPLATES \
template <typename ValueType, typename BatchMatrixType, typename PrecType> \
GKO_DECLARE_BATCH_CG_APPLY_KERNEL(ValueType, BatchMatrixType, PrecType)


GKO_DECLARE_FOR_ALL_EXECUTOR_NAMESPACES(batch_cg, GKO_DECLARE_ALL_AS_TEMPLATES);
Expand Down
Loading