2
0
mirror of https://github.com/boostorg/compute.git synced 2026-01-27 18:52:15 +00:00

Merge pull request #168 from kylelutz/struct-is-packed

Add check for packed structs in BOOST_COMPUTE_ADAPT_STRUCT()
This commit is contained in:
Kyle Lutz
2014-07-07 08:01:50 -07:00

View File

@@ -13,8 +13,12 @@
#include <sstream>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/compute/type_traits/type_name.hpp>
#include <boost/compute/detail/meta_kernel.hpp>
@@ -42,6 +46,30 @@ inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
&type::member, BOOST_PP_STRINGIZE(member) \
)
/// \internal_
#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE(s, struct_, member_) \
sizeof(((struct_ *)0)->member_)
/// \internal_
#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD(s, x, y) (x+y)
/// \internal_
#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_) \
BOOST_PP_SEQ_FOLD_LEFT( \
BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD, \
0, \
BOOST_PP_SEQ_TRANSFORM( \
BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE, struct_, members_ \
) \
)
/// \internal_
///
/// Returns true if struct_ contains no internal padding bytes (i.e. it is
/// packed). members_ is a sequence of the names of the struct members.
#define BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(struct_, members_) \
(sizeof(struct_) == BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_))
/// The BOOST_COMPUTE_ADAPT_STRUCT() macro makes a C++ struct/class available
/// to OpenCL kernels.
///
@@ -80,7 +108,17 @@ inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
/// particles.begin(), particles.end(), sort_by_x, queue
/// );
/// \endcode
///
/// Due to differences in struct padding between the host compiler and the
/// device compiler, the \c BOOST_COMPUTE_ADAPT_STRUCT() macro requires that
/// the adapted struct is packed (i.e. no padding bytes between members).
///
/// \see type_name()
#define BOOST_COMPUTE_ADAPT_STRUCT(type, name, members) \
BOOST_STATIC_ASSERT_MSG( \
BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(type, BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members)), \
"BOOST_COMPUTE_ADAPT_STRUCT() does not support structs with internal padding." \
); \
BOOST_COMPUTE_TYPE_NAME(type, name) \
namespace boost { namespace compute { namespace detail { \
template<> \
@@ -89,7 +127,7 @@ inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
void operator()(meta_kernel &kernel) \
{ \
std::stringstream declaration; \
declaration << "typedef struct {\n" \
declaration << "typedef struct __attribute__((packed)) {\n" \
BOOST_PP_SEQ_FOR_EACH( \
BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER, \
type, \