Commit 51e3b2bb authored by Kenneth Moreland's avatar Kenneth Moreland
Browse files

Add checks for signature tags

It's easy to put accidently put something that is not a valid tag in a
ControlSignature or ExecutionSignature. Previously, when you did that
you got a weird error at the end of a very long template instantiation
chain that made it difficult to find the offending worklet.

This adds some type checks when the dispatcher is instantated to check
the signatures. It doesn't point directly to the signature or its
parameter, but it is much closer.
parent 40efb513
......@@ -21,6 +21,7 @@
include_directories(${Boost_INCLUDE_DIRS})
set(headers
ControlSignatureTagBase.h
Transport.h
TransportTagArrayIn.h
TransportTagArrayOut.h
......
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_arg_ControlSignatureTagBase_h
#define vtk_m_cont_arg_ControlSignatureTagBase_h
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace vtkm {
namespace cont {
namespace arg {
/// \brief The base class for all tags used in a \c ControlSignature.
///
/// If a new \c ControlSignature tag is created, it must be derived from this
/// class in some way. This helps identify \c ControlSignature tags in the \c
/// VTKM_IS_CONTROL_SIGNATURE_TAG macro and allows checking the validity of a
/// \c ControlSignature.
///
/// In addition to inheriting from this base class, a \c ControlSignature tag
/// must define the following three typedefs: \c TypeCheckTag, \c TransportTag
/// and \c FetchTag.
///
struct ControlSignatureTagBase { };
namespace internal {
template<typename ControlSignatureTag>
struct ControlSignatureTagCheck
{
static const bool Valid =
boost::is_base_of<
vtkm::cont::arg::ControlSignatureTagBase, ControlSignatureTag>::value;
};
} // namespace internal
/// Checks that the argument is a proper tag for an \c ControlSignature. This
/// is a handy concept check when modifying tags or dispatching to make sure
/// that a template argument is actually an \c ControlSignature tag. (You can
/// get weird errors elsewhere in the code when a mistake is made.)
///
#define VTKM_IS_CONTROL_SIGNATURE_TAG(tag) \
BOOST_STATIC_ASSERT_MSG( \
::vtkm::cont::arg::internal::ControlSignatureTagCheck<tag>::Valid, \
"Provided a type that is not a valid ControlSignature tag.")
}
}
} // namespace vtkm::cont::arg
#endif //vtk_m_cont_arg_ControlSignatureTagBase_h
......@@ -19,6 +19,7 @@
##============================================================================
set(unit_tests
UnitTestControlSignatureTag.cxx
UnitTestTransportArrayIn.cxx
UnitTestTransportArrayOut.cxx
UnitTestTransportExecObject.cxx
......
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
void TestControlSignatures()
{
VTKM_IS_CONTROL_SIGNATURE_TAG(
vtkm::worklet::WorkletMapField::FieldIn<vtkm::Float32>);
VTKM_TEST_ASSERT(
vtkm::cont::arg::internal::ControlSignatureTagCheck<
vtkm::worklet::WorkletMapField::FieldIn<vtkm::Id> >::Valid,
"Bad check for FieldIn");
VTKM_TEST_ASSERT(
vtkm::cont::arg::internal::ControlSignatureTagCheck<
vtkm::worklet::WorkletMapField::FieldOut<vtkm::Id> >::Valid,
"Bad check for FieldOut");
VTKM_TEST_ASSERT(
!vtkm::cont::arg::internal::ControlSignatureTagCheck<
vtkm::exec::arg::WorkIndex >::Valid,
"Bad check for WorkIndex");
VTKM_TEST_ASSERT(
!vtkm::cont::arg::internal::ControlSignatureTagCheck<vtkm::Id>::Valid,
"Bad check for vtkm::Id");
}
} // anonymous namespace
int UnitTestControlSignatureTag(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestControlSignatures);
}
......@@ -23,6 +23,7 @@
#include <vtkm/Types.h>
#include <vtkm/exec/arg/AspectTagDefault.h>
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
namespace vtkm {
namespace exec {
......@@ -35,7 +36,7 @@ namespace arg {
/// this class.
///
template<vtkm::IdComponent ControlSignatureIndex>
struct BasicArg
struct BasicArg : vtkm::exec::arg::ExecutionSignatureTagBase
{
static const vtkm::IdComponent INDEX = ControlSignatureIndex;
typedef vtkm::exec::arg::AspectTagDefault AspectTag;
......
......@@ -21,6 +21,7 @@
set(headers
AspectTagDefault.h
BasicArg.h
ExecutionSignatureTagBase.h
Fetch.h
FetchTagArrayDirectIn.h
FetchTagArrayDirectOut.h
......
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_arg_ExecutionSignatureTagBase_h
#define vtk_m_exec_arg_ExecutionSignatureTagBase_h
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace vtkm {
namespace exec {
namespace arg {
/// \brief The base class for all tags used in an \c ExecutionSignature.
///
/// If a new \c ExecutionSignature tag is created, it must be derived from this
/// class in some way. This helps identify \c ExecutionSignature tags in the \c
/// VTKM_IS_EXECUTION_SIGNATURE_TAG macro and allows checking the validity of
/// an \c ExecutionSignature.
///
/// In addition to inheriting from this base class, an \c ExecutionSignature
/// tag must define a \c static \c const \c vtkm::IdComponent named \c INDEX
/// that points to a parameter in the \c ControlSignature and a \c typedef
/// named \c AspectTag that defines the aspect of the fetch.
///
struct ExecutionSignatureTagBase { };
namespace internal {
template<typename ExecutionSignatureTag>
struct ExecutionSignatureTagCheck
{
static const bool Valid =
boost::is_base_of<
vtkm::exec::arg::ExecutionSignatureTagBase, ExecutionSignatureTag>::
value;
};
} // namespace internal
/// Checks that the argument is a proper tag for an \c ExecutionSignature. This
/// is a handy concept check when modifying tags or dispatching to make sure
/// that a template argument is actually an \c ExecutionSignature tag. (You can
/// get weird errors elsewhere in the code when a mistake is made.)
///
#define VTKM_IS_EXECUTION_SIGNATURE_TAG(tag) \
BOOST_STATIC_ASSERT_MSG( \
::vtkm::exec::arg::internal::ExecutionSignatureTagCheck<tag>::Valid, \
"Provided a type that is not a valid ExecutionSignature tag.")
}
}
} // namespace vtkm::exec::arg
#endif //vtk_m_exec_arg_ExecutionSignatureTagBase_h
......@@ -21,6 +21,7 @@
#define vtk_m_exec_arg_WorkIndex_h
#include <vtkm/exec/arg/Fetch.h>
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
namespace vtkm {
namespace exec {
......@@ -40,7 +41,7 @@ struct AspectTagWorkIndex { };
/// ExecutionSignature passes the index for this work. \c WorkletBase contains
/// a typedef that points to this class.
///
struct WorkIndex
struct WorkIndex : vtkm::exec::arg::ExecutionSignatureTagBase
{
// The index does not really matter because the fetch is going to ignore it.
// However, it still has to point to a valid parameter in the
......
......@@ -19,6 +19,7 @@
##============================================================================
set(unit_tests
UnitTestExecutionSignatureTag.cxx
UnitTestFetchArrayDirectIn.cxx
UnitTestFetchArrayDirectOut.cxx
UnitTestFetchExecObject.cxx
......
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/exec/arg/BasicArg.h>
#include <vtkm/exec/arg/WorkIndex.h>
#include <vtkm/testing/Testing.h>
namespace {
void TestExecutionSignatures()
{
VTKM_IS_EXECUTION_SIGNATURE_TAG(vtkm::exec::arg::BasicArg<1>);
VTKM_TEST_ASSERT(
vtkm::exec::arg::internal::ExecutionSignatureTagCheck<
vtkm::exec::arg::BasicArg<2> >::Valid,
"Bad check for BasicArg");
VTKM_TEST_ASSERT(
vtkm::exec::arg::internal::ExecutionSignatureTagCheck<
vtkm::exec::arg::WorkIndex >::Valid,
"Bad check for WorkIndex");
VTKM_TEST_ASSERT(
!vtkm::exec::arg::internal::ExecutionSignatureTagCheck<vtkm::Id>::Valid,
"Bad check for vtkm::Id");
}
} // anonymous namespace
int UnitTestExecutionSignatureTag(int, char *[])
{
return vtkm::testing::Testing::Run(TestExecutionSignatures);
}
......@@ -24,6 +24,7 @@
#include <vtkm/TypeListTag.h>
#include <vtkm/cont/arg/ControlSignatureTagBase.h>
#include <vtkm/cont/arg/TransportTagArrayIn.h>
#include <vtkm/cont/arg/TransportTagArrayOut.h>
#include <vtkm/cont/arg/TypeCheckTagArray.h>
......@@ -47,7 +48,7 @@ public:
/// the possible value types in the array.
///
template<typename TypeList = AllTypes>
struct FieldIn {
struct FieldIn : vtkm::cont::arg::ControlSignatureTagBase {
typedef vtkm::cont::arg::TypeCheckTagArray<TypeList> TypeCheckTag;
typedef vtkm::cont::arg::TransportTagArrayIn TransportTag;
typedef vtkm::exec::arg::FetchTagArrayDirectIn FetchTag;
......@@ -59,7 +60,7 @@ public:
/// the possible value types in the array.
///
template<typename TypeList = AllTypes>
struct FieldOut {
struct FieldOut : vtkm::cont::arg::ControlSignatureTagBase {
typedef vtkm::cont::arg::TypeCheckTagArray<TypeList> TypeCheckTag;
typedef vtkm::cont::arg::TransportTagArrayOut TransportTag;
typedef vtkm::exec::arg::FetchTagArrayDirectOut FetchTag;
......
......@@ -26,11 +26,14 @@
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ErrorControlBadType.h>
#include <vtkm/cont/arg/ControlSignatureTagBase.h>
#include <vtkm/cont/arg/Transport.h>
#include <vtkm/cont/arg/TypeCheck.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <boost/mpl/assert.hpp>
......@@ -46,6 +49,34 @@ namespace internal {
namespace detail {
// Checks that an argument in a ControlSignature is a valid control signature
// tag. Causes a compile error otherwise.
struct DispatcherBaseControlSignatureTagCheck
{
template<typename ControlSignatureTag>
struct ReturnType {
// If you get a compile error here, it means there is something that is
// not a valid control signature tag in a worklet's ControlSignature.
VTKM_IS_CONTROL_SIGNATURE_TAG(ControlSignatureTag);
typedef ControlSignatureTag type;
};
};
// Checks that an argument in a ExecutionSignature is a valid execution
// signature tag. Causes a compile error otherwise.
struct DispatcherBaseExecutionSignatureTagCheck
{
template<typename ExecutionSignatureTag>
struct ReturnType {
// If you get a compile error here, it means there is something that is not
// a valid execution signature tag in a worklet's ExecutionSignature.
VTKM_IS_EXECUTION_SIGNATURE_TAG(ExecutionSignatureTag);
typedef ExecutionSignatureTag type;
};
};
// Used in the dynamic cast to check to make sure that the type passed into
// the Invoke method matches the type accepted by the ControlSignature.
template<typename ContinueFunctor, typename TypeCheckTag>
struct DispatcherBaseTypeCheckFunctor
{
......@@ -86,6 +117,9 @@ struct DispatcherBaseTypeCheckFunctor
}
};
// Uses vtkm::cont::internal::DynamicTransform and the DynamicTransformCont
// method of FunctionInterface to convert all DynamicArrayHandles and any
// other arguments declaring themselves as dynamic to static versions.
struct DispatcherBaseDynamicTransform
{
vtkm::cont::internal::DynamicTransform BasicDynamicTransform;
......@@ -116,6 +150,8 @@ struct DispatcherBaseDynamicTransform
}
};
// A functor called at the end of the dynamic transform to call the next
// step in the dynamic transform.
template<typename DispatcherBaseType>
struct DispatcherBaseDynamicTransformHelper
{
......@@ -132,6 +168,8 @@ struct DispatcherBaseDynamicTransformHelper
}
};
// A functor used in a StaticCast of a FunctionInterface to transport arguments
// from the control environment to the execution environment.
template<typename Device>
struct DispatcherBaseTransportFunctor
{
......@@ -186,6 +224,18 @@ protected:
static const vtkm::IdComponent NUM_INVOKE_PARAMS = ControlInterface::ARITY;
private:
// We don't really need these types, but declaring them checks the arguments
// of the control and execution signatures.
typedef typename ControlInterface::
template StaticTransformType<
detail::DispatcherBaseControlSignatureTagCheck>::type
ControlSignatureCheck;
typedef typename ExecutionInterface::
template StaticTransformType<
detail::DispatcherBaseExecutionSignatureTagCheck>::type
ExecutionSignatureCheck;
template<typename Signature>
VTKM_CONT_EXPORT
void StartInvoke(
......
......@@ -22,6 +22,8 @@
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/arg/ControlSignatureTagBase.h>
#include <vtkm/worklet/internal/WorkletBase.h>
#include <vtkm/cont/testing/Testing.h>
......@@ -128,12 +130,12 @@ namespace {
class TestWorkletBase : public vtkm::worklet::internal::WorkletBase
{
public:
struct TestIn {
struct TestIn : vtkm::cont::arg::ControlSignatureTagBase {
typedef TestTypeCheckTag TypeCheckTag;
typedef TestTransportTag TransportTag;
typedef TestFetchTagInput FetchTag;
};
struct TestOut {
struct TestOut : vtkm::cont::arg::ControlSignatureTagBase {
typedef TestTypeCheckTag TypeCheckTag;
typedef TestTransportTag TransportTag;
typedef TestFetchTagOutput FetchTag;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment