Bug 1113379 - Convert ctypes/typedefs.h into a series of higher-order macros, for better code hygiene and to work around an incredible oddity in NetBSD's <stdint.h>. r=jorendorff

This commit is contained in:
Jeff Walden 2015-01-09 02:07:39 -08:00
parent d6f1d7deef
commit 48ba709893
5 changed files with 195 additions and 167 deletions

View File

@ -1276,7 +1276,8 @@ InitTypeClasses(JSContext* cx, HandleObject parent)
INT_TO_JSVAL(ffiType.alignment), &ffiType)); \
if (!typeObj_##name) \
return false;
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_TYPE(DEFINE_TYPE)
#undef DEFINE_TYPE
// Alias 'ctypes.unsigned' as 'ctypes.unsigned_int', since they represent
// the same type in C.
@ -1666,14 +1667,15 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result)
// Check whether the source type is always representable, with exact
// precision, by the target type. If it is, convert the value.
switch (CType::GetTypeCode(typeObj)) {
#define DEFINE_INT_TYPE(name, fromType, ffiType) \
#define INTEGER_CASE(name, fromType, ffiType) \
case TYPE_##name: \
if (!IsAlwaysExact<IntegerType, fromType>()) \
return false; \
*result = IntegerType(*static_cast<fromType*>(data)); \
return true;
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_INT_TYPE(INTEGER_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGER_CASE)
#undef INTEGER_CASE
case TYPE_void_t:
case TYPE_bool:
case TYPE_float:
@ -1755,15 +1757,16 @@ jsvalToFloat(JSContext *cx, jsval val, FloatType* result)
// Check whether the source type is always representable, with exact
// precision, by the target type. If it is, convert the value.
switch (CType::GetTypeCode(typeObj)) {
#define DEFINE_FLOAT_TYPE(name, fromType, ffiType) \
#define NUMERIC_CASE(name, fromType, ffiType) \
case TYPE_##name: \
if (!IsAlwaysExact<FloatType, fromType>()) \
return false; \
*result = FloatType(*static_cast<fromType*>(data)); \
return true;
#define DEFINE_INT_TYPE(x, y, z) DEFINE_FLOAT_TYPE(x, y, z)
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_FLOAT_TYPE(NUMERIC_CASE)
CTYPES_FOR_EACH_INT_TYPE(NUMERIC_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(NUMERIC_CASE)
#undef NUMERIC_CASE
case TYPE_void_t:
case TYPE_bool:
case TYPE_char:
@ -2130,7 +2133,7 @@ ConvertToJS(JSContext* cx,
case TYPE_bool:
result.setBoolean(*static_cast<bool*>(data));
break;
#define DEFINE_INT_TYPE(name, type, ffiType) \
#define INT_CASE(name, type, ffiType) \
case TYPE_##name: { \
type value = *static_cast<type*>(data); \
if (sizeof(type) < 4) \
@ -2139,7 +2142,9 @@ ConvertToJS(JSContext* cx,
result.setDouble(double(value)); \
break; \
}
#define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_INT_TYPE(INT_CASE)
#undef INT_CASE
#define WRAPPED_INT_CASE(name, type, ffiType) \
case TYPE_##name: { \
/* Return an Int64 or UInt64 object - do not convert to a JS number. */ \
uint64_t value; \
@ -2165,19 +2170,24 @@ ConvertToJS(JSContext* cx,
result.setObject(*obj); \
break; \
}
#define DEFINE_FLOAT_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(WRAPPED_INT_CASE)
#undef WRAPPED_INT_CASE
#define FLOAT_CASE(name, type, ffiType) \
case TYPE_##name: { \
type value = *static_cast<type*>(data); \
result.setDouble(double(value)); \
break; \
}
#define DEFINE_CHAR_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_FLOAT_TYPE(FLOAT_CASE)
#undef FLOAT_CASE
#define CHAR_CASE(name, type, ffiType) \
case TYPE_##name: \
/* Convert to an integer. We have no idea what character encoding to */ \
/* use, if any. */ \
result.setInt32(*static_cast<type*>(data)); \
break;
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_CHAR_TYPE(CHAR_CASE)
#undef CHAR_CASE
case TYPE_char16_t: {
// Convert the char16_t to a 1-character string.
JSString* str = JS_NewUCStringCopyN(cx, static_cast<char16_t*>(data), 1);
@ -2326,26 +2336,7 @@ ImplicitConvert(JSContext* cx,
*static_cast<bool*>(buffer) = result;
break;
}
#define DEFINE_INT_TYPE(name, type, ffiType) \
case TYPE_##name: { \
/* Do not implicitly lose bits. */ \
type result; \
if (!jsvalToInteger(cx, val, &result)) \
return TypeError(cx, #name, val); \
*static_cast<type*>(buffer) = result; \
break; \
}
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_FLOAT_TYPE(name, type, ffiType) \
case TYPE_##name: { \
type result; \
if (!jsvalToFloat(cx, val, &result)) \
return TypeError(cx, #name, val); \
*static_cast<type*>(buffer) = result; \
break; \
}
#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR16_TYPE(name, type, ffiType) \
#define CHAR16_CASE(name, type, ffiType) \
case TYPE_##name: { \
/* Convert from a 1-character string, regardless of encoding, */ \
/* or from an integer, provided the result fits in 'type'. */ \
@ -2364,7 +2355,35 @@ ImplicitConvert(JSContext* cx,
*static_cast<type*>(buffer) = result; \
break; \
}
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_CHAR16_TYPE(CHAR16_CASE)
#undef CHAR16_CASE
#define INTEGRAL_CASE(name, type, ffiType) \
case TYPE_##name: { \
/* Do not implicitly lose bits. */ \
type result; \
if (!jsvalToInteger(cx, val, &result)) \
return TypeError(cx, #name, val); \
*static_cast<type*>(buffer) = result; \
break; \
}
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGRAL_CASE)
// It's hard to believe ctypes.char16_t("f") should work yet ctypes.char("f")
// should not. Ditto for ctypes.{un,}signed_char. But this is how ctypes
// has always worked, so preserve these semantics, and don't switch to an
// algorithm similar to that in DEFINE_CHAR16_TYPE above, just yet.
CTYPES_FOR_EACH_CHAR_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
#define FLOAT_CASE(name, type, ffiType) \
case TYPE_##name: { \
type result; \
if (!jsvalToFloat(cx, val, &result)) \
return TypeError(cx, #name, val); \
*static_cast<type*>(buffer) = result; \
break; \
}
CTYPES_FOR_EACH_FLOAT_TYPE(FLOAT_CASE)
#undef FLOAT_CASE
case TYPE_pointer: {
if (val.isNull()) {
// Convert to a null pointer.
@ -2707,7 +2726,7 @@ ExplicitConvert(JSContext* cx, HandleValue val, HandleObject targetType, void* b
*static_cast<bool*>(buffer) = ToBoolean(val);
break;
}
#define DEFINE_INT_TYPE(name, type, ffiType) \
#define INTEGRAL_CASE(name, type, ffiType) \
case TYPE_##name: { \
/* Convert numeric values with a C-style cast, and */ \
/* allow conversion from a base-10 or base-16 string. */ \
@ -2719,10 +2738,11 @@ ExplicitConvert(JSContext* cx, HandleValue val, HandleObject targetType, void* b
*static_cast<type*>(buffer) = result; \
break; \
}
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR16_TYPE(x, y, z) DEFINE_CHAR_TYPE(x, y, z)
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR16_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
case TYPE_pointer: {
// Convert a number, Int64 object, or UInt64 object to a pointer.
uintptr_t result;
@ -2875,9 +2895,9 @@ BuildTypeSource(JSContext* cx,
// Walk the types, building up the toSource() string.
switch (CType::GetTypeCode(typeObj)) {
case TYPE_void_t:
#define DEFINE_TYPE(name, type, ffiType) \
case TYPE_##name:
#include "ctypes/typedefs.h"
#define CASE_FOR_TYPE(name, type, ffiType) case TYPE_##name:
CTYPES_FOR_EACH_TYPE(CASE_FOR_TYPE)
#undef CASE_FOR_TYPE
{
AppendString(result, "ctypes.");
JSString* nameStr = CType::GetName(cx, typeObj);
@ -3026,12 +3046,14 @@ BuildDataSource(JSContext* cx,
else
AppendString(result, "false");
break;
#define DEFINE_INT_TYPE(name, type, ffiType) \
#define INTEGRAL_CASE(name, type, ffiType) \
case TYPE_##name: \
/* Serialize as a primitive decimal integer. */ \
IntegerToString(*static_cast<type*>(data), 10, result); \
break;
#define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
#define WRAPPED_INT_CASE(name, type, ffiType) \
case TYPE_##name: \
/* Serialize as a wrapped decimal integer. */ \
if (!NumericLimits<type>::is_signed) \
@ -3042,7 +3064,9 @@ BuildDataSource(JSContext* cx,
IntegerToString(*static_cast<type*>(data), 10, result); \
AppendString(result, "\")"); \
break;
#define DEFINE_FLOAT_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(WRAPPED_INT_CASE)
#undef WRAPPED_INT_CASE
#define FLOAT_CASE(name, type, ffiType) \
case TYPE_##name: { \
/* Serialize as a primitive double. */ \
double fp = *static_cast<type*>(data); \
@ -3056,12 +3080,15 @@ BuildDataSource(JSContext* cx,
result.append(str, strlen(str)); \
break; \
}
#define DEFINE_CHAR_TYPE(name, type, ffiType) \
CTYPES_FOR_EACH_FLOAT_TYPE(FLOAT_CASE)
#undef FLOAT_CASE
#define CHAR_CASE(name, type, ffiType) \
case TYPE_##name: \
/* Serialize as an integer. */ \
IntegerToString(*static_cast<type*>(data), 10, result); \
break;
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_CHAR_TYPE(CHAR_CASE)
#undef CHAR_CASE
case TYPE_char16_t: {
// Serialize as a 1-character JS string.
JSString* str = JS_NewUCStringCopyN(cx, static_cast<char16_t*>(data), 1);
@ -5939,18 +5966,19 @@ FunctionType::Call(JSContext* cx,
// Small integer types get returned as a word-sized ffi_arg. Coerce it back
// into the correct size for ConvertToJS.
switch (typeCode) {
#define DEFINE_INT_TYPE(name, type, ffiType) \
#define INTEGRAL_CASE(name, type, ffiType) \
case TYPE_##name: \
if (sizeof(type) < sizeof(ffi_arg)) { \
ffi_arg data = *static_cast<ffi_arg*>(returnValue.mData); \
*static_cast<type*>(returnValue.mData) = static_cast<type>(data); \
} \
break;
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR16_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_BOOL_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR16_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
default:
break;
}
@ -6211,13 +6239,13 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
if (cif->rtype != &ffi_type_void) {
rvSize = cif->rtype->size;
switch (typeCode) {
#define DEFINE_INT_TYPE(name, type, ffiType) \
case TYPE_##name:
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR16_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#include "ctypes/typedefs.h"
#define INTEGRAL_CASE(name, type, ffiType) case TYPE_##name:
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_BOOL_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR16_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
rvSize = Align(rvSize, sizeof(ffi_arg));
break;
default:
@ -6292,18 +6320,19 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
// Small integer types must be returned as a word-sized ffi_arg. Coerce it
// back into the size libffi expects.
switch (typeCode) {
#define DEFINE_INT_TYPE(name, type, ffiType) \
#define INTEGRAL_CASE(name, type, ffiType) \
case TYPE_##name: \
if (sizeof(type) < sizeof(ffi_arg)) { \
ffi_arg data = *static_cast<type*>(result); \
*static_cast<ffi_arg*>(result) = data; \
} \
break;
#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#define DEFINE_CHAR16_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_BOOL_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR_TYPE(INTEGRAL_CASE)
CTYPES_FOR_EACH_CHAR16_TYPE(INTEGRAL_CASE)
#undef INTEGRAL_CASE
default:
break;
}

View File

@ -10,6 +10,7 @@
#include "jsalloc.h"
#include "prlink.h"
#include "ctypes/typedefs.h"
#include "js/HashTable.h"
#include "js/Vector.h"
#include "vm/String.h"
@ -224,7 +225,8 @@ enum ABICode {
enum TypeCode {
TYPE_void_t,
#define DEFINE_TYPE(name, type, ffiType) TYPE_##name,
#include "ctypes/typedefs.h"
CTYPES_FOR_EACH_TYPE(DEFINE_TYPE)
#undef DEFINE_TYPE
TYPE_pointer,
TYPE_function,
TYPE_array,

View File

@ -5,50 +5,32 @@
/**
* This header contains the builtin types available for arguments and return
* values, representing their C counterparts. They are listed inside macros
* that the #includer is expected to #define. Format is:
* values, representing their C counterparts. They are used inside higher-order
* macros that the user must call, providing a macro that will consume the
* arguments provided to it by the higher-order macro. The macros exposed are:
*
* DEFINE_X_TYPE(typename, ctype, ffitype)
* CTYPES_FOR_EACH_BOOL_TYPE(macro)
* CTYPES_FOR_EACH_CHAR_TYPE(macro)
* CTYPES_FOR_EACH_CHAR16_TYPE(macro)
* CTYPES_FOR_EACH_INT_TYPE(macro)
* CTYPES_FOR_EACH_WRAPPED_INT_TYPE(macro)
* CTYPES_FOR_EACH_FLOAT_TYPE(macro)
* CTYPES_FOR_EACH_TYPE(macro)
*
* The macro name provided to any of these macros will then be repeatedly
* invoked as
*
* macro(typename, ctype, ffitype)
*
* where 'typename' is the name of the type constructor (accessible as
* ctypes.typename), 'ctype' is the corresponding C type declaration (from
* which sizeof(ctype) and templated type conversions will be derived), and
* 'ffitype' is the ffi_type to use. (Special types, such as 'void' and the
* pointer, array, and struct types are handled separately.)
*
* This header lacks a #ifndef wrapper because it is deliberately #included
* multiple times in ctypes/CTypes.h.
*/
// If we're not breaking the types out, combine them together under one
// DEFINE_TYPE macro. Otherwise, turn off whichever ones we're not using.
#if defined(DEFINE_TYPE)
# define DEFINE_CHAR_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_CHAR16_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_BOOL_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_FLOAT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
#else
# ifndef DEFINE_BOOL_TYPE
# define DEFINE_BOOL_TYPE(x, y, z)
# endif
# ifndef DEFINE_CHAR_TYPE
# define DEFINE_CHAR_TYPE(x, y, z)
# endif
# ifndef DEFINE_CHAR16_TYPE
# define DEFINE_CHAR16_TYPE(x, y, z)
# endif
# ifndef DEFINE_INT_TYPE
# define DEFINE_INT_TYPE(x, y, z)
# endif
# ifndef DEFINE_WRAPPED_INT_TYPE
# define DEFINE_WRAPPED_INT_TYPE(x, y, z)
# endif
# ifndef DEFINE_FLOAT_TYPE
# define DEFINE_FLOAT_TYPE(x, y, z)
# endif
#endif
#ifndef ctypes_typedefs_h
#define ctypes_typedefs_h
// MSVC doesn't have ssize_t. Help it along a little.
#ifdef HAVE_SSIZE_T
@ -71,52 +53,54 @@
#define CTYPES_FFI_INTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_UINTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_uint32 : ffi_type_uint64)
// The meat.
DEFINE_BOOL_TYPE (bool, bool, CTYPES_FFI_BOOL)
DEFINE_INT_TYPE (int8_t, int8_t, ffi_type_sint8)
DEFINE_INT_TYPE (int16_t, int16_t, ffi_type_sint16)
DEFINE_INT_TYPE (int32_t, int32_t, ffi_type_sint32)
DEFINE_INT_TYPE (uint8_t, uint8_t, ffi_type_uint8)
DEFINE_INT_TYPE (uint16_t, uint16_t, ffi_type_uint16)
DEFINE_INT_TYPE (uint32_t, uint32_t, ffi_type_uint32)
DEFINE_INT_TYPE (short, short, ffi_type_sint16)
DEFINE_INT_TYPE (unsigned_short, unsigned short, ffi_type_uint16)
DEFINE_INT_TYPE (int, int, ffi_type_sint32)
DEFINE_INT_TYPE (unsigned_int, unsigned int, ffi_type_uint32)
DEFINE_WRAPPED_INT_TYPE(int64_t, int64_t, ffi_type_sint64)
DEFINE_WRAPPED_INT_TYPE(uint64_t, uint64_t, ffi_type_uint64)
DEFINE_WRAPPED_INT_TYPE(long, long, CTYPES_FFI_LONG)
DEFINE_WRAPPED_INT_TYPE(unsigned_long, unsigned long, CTYPES_FFI_ULONG)
DEFINE_WRAPPED_INT_TYPE(long_long, long long, ffi_type_sint64)
DEFINE_WRAPPED_INT_TYPE(unsigned_long_long, unsigned long long, ffi_type_uint64)
DEFINE_WRAPPED_INT_TYPE(size_t, size_t, CTYPES_FFI_SIZE_T)
DEFINE_WRAPPED_INT_TYPE(ssize_t, CTYPES_SSIZE_T, CTYPES_FFI_SSIZE_T)
DEFINE_WRAPPED_INT_TYPE(off_t, off_t, CTYPES_FFI_OFF_T)
DEFINE_WRAPPED_INT_TYPE(intptr_t, intptr_t, CTYPES_FFI_INTPTR_T)
DEFINE_WRAPPED_INT_TYPE(uintptr_t, uintptr_t, CTYPES_FFI_UINTPTR_T)
DEFINE_FLOAT_TYPE (float32_t, float, ffi_type_float)
DEFINE_FLOAT_TYPE (float64_t, double, ffi_type_double)
DEFINE_FLOAT_TYPE (float, float, ffi_type_float)
DEFINE_FLOAT_TYPE (double, double, ffi_type_double)
DEFINE_CHAR_TYPE (char, char, ffi_type_uint8)
DEFINE_CHAR_TYPE (signed_char, signed char, ffi_type_sint8)
DEFINE_CHAR_TYPE (unsigned_char, unsigned char, ffi_type_uint8)
DEFINE_CHAR16_TYPE (char16_t, char16_t, ffi_type_uint16)
#define CTYPES_FOR_EACH_BOOL_TYPE(macro) \
macro(bool, bool, CTYPES_FFI_BOOL)
#undef CTYPES_SSIZE_T
#undef CTYPES_FFI_BOOL
#undef CTYPES_FFI_LONG
#undef CTYPES_FFI_ULONG
#undef CTYPES_FFI_SIZE_T
#undef CTYPES_FFI_SSIZE_T
#undef CTYPES_FFI_INTPTR_T
#undef CTYPES_FFI_UINTPTR_T
#define CTYPES_FOR_EACH_INT_TYPE(macro) \
macro(int8_t, int8_t, ffi_type_sint8) \
macro(int16_t, int16_t, ffi_type_sint16) \
macro(int32_t, int32_t, ffi_type_sint32) \
macro(uint8_t, uint8_t, ffi_type_uint8) \
macro(uint16_t, uint16_t, ffi_type_uint16) \
macro(uint32_t, uint32_t, ffi_type_uint32) \
macro(short, short, ffi_type_sint16) \
macro(unsigned_short, unsigned short, ffi_type_uint16) \
macro(int, int, ffi_type_sint32) \
macro(unsigned_int, unsigned int, ffi_type_uint32)
#undef DEFINE_TYPE
#undef DEFINE_CHAR_TYPE
#undef DEFINE_CHAR16_TYPE
#undef DEFINE_BOOL_TYPE
#undef DEFINE_INT_TYPE
#undef DEFINE_WRAPPED_INT_TYPE
#undef DEFINE_FLOAT_TYPE
#define CTYPES_FOR_EACH_WRAPPED_INT_TYPE(macro) \
macro(int64_t, int64_t, ffi_type_sint64) \
macro(uint64_t, uint64_t, ffi_type_uint64) \
macro(long, long, CTYPES_FFI_LONG) \
macro(unsigned_long, unsigned long, CTYPES_FFI_ULONG) \
macro(long_long, long long, ffi_type_sint64) \
macro(unsigned_long_long, unsigned long long, ffi_type_uint64) \
macro(size_t, size_t, CTYPES_FFI_SIZE_T) \
macro(ssize_t, CTYPES_SSIZE_T, CTYPES_FFI_SSIZE_T) \
macro(off_t, off_t, CTYPES_FFI_OFF_T) \
macro(intptr_t, intptr_t, CTYPES_FFI_INTPTR_T) \
macro(uintptr_t, uintptr_t, CTYPES_FFI_UINTPTR_T)
#define CTYPES_FOR_EACH_FLOAT_TYPE(macro) \
macro(float32_t, float, ffi_type_float) \
macro(float64_t, double, ffi_type_double) \
macro(float, float, ffi_type_float) \
macro(double, double, ffi_type_double)
#define CTYPES_FOR_EACH_CHAR_TYPE(macro) \
macro(char, char, ffi_type_uint8) \
macro(signed_char, signed char, ffi_type_sint8) \
macro(unsigned_char, unsigned char, ffi_type_uint8)
#define CTYPES_FOR_EACH_CHAR16_TYPE(macro) \
macro(char16_t, char16_t, ffi_type_uint16)
#define CTYPES_FOR_EACH_TYPE(macro) \
CTYPES_FOR_EACH_BOOL_TYPE(macro) \
CTYPES_FOR_EACH_INT_TYPE(macro) \
CTYPES_FOR_EACH_WRAPPED_INT_TYPE(macro) \
CTYPES_FOR_EACH_FLOAT_TYPE(macro) \
CTYPES_FOR_EACH_CHAR_TYPE(macro) \
CTYPES_FOR_EACH_CHAR16_TYPE(macro)
#endif /* ctypes_typedefs_h */

View File

@ -7,6 +7,7 @@
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include "typedefs.h"
#if defined(XP_WIN)
#define snprintf _snprintf
@ -43,39 +44,47 @@ test_void_t_cdecl()
return;
}
#define FUNCTION_TESTS(name, type, ffiType, suffix) \
// The "AndUnderscore" bit here is an unfortunate hack: the first argument to
// DEFINE_CDECL_FUNCTIONS and DEFINE_STDCALL_FUNCTIONS, in addition to being a
// type, may also be a *macro* on NetBSD -- #define int8_t __int8_t and so on.
// See <http://mail-index.netbsd.org/tech-toolchain/2014/12/18/msg002479.html>.
// And unfortunately, passing that macro as an argument to this macro causes it
// to be expanded -- producing get___int8_t_cdecl() and so on. Concatenating
// int8_t with _ slightly muddies this code but inhibits expansion. See also
// bug 1113379.
#define FUNCTION_TESTS(nameAndUnderscore, type, ffiType, suffix) \
type ABI \
get_##name##_##suffix() \
get_##nameAndUnderscore##suffix() \
{ \
return ValueTraits<type>::literal(); \
} \
\
type ABI \
set_##name##_##suffix(type x) \
set_##nameAndUnderscore##suffix(type x) \
{ \
return x; \
} \
\
type ABI \
sum_##name##_##suffix(type x, type y) \
sum_##nameAndUnderscore##suffix(type x, type y) \
{ \
return ValueTraits<type>::sum(x, y); \
} \
\
type ABI \
sum_alignb_##name##_##suffix(char a, type x, char b, type y, char c) \
sum_alignb_##nameAndUnderscore##suffix(char a, type x, char b, type y, char c)\
{ \
return ValueTraits<type>::sum(x, y); \
} \
\
type ABI \
sum_alignf_##name##_##suffix(float a, type x, float b, type y, float c) \
sum_alignf_##nameAndUnderscore##suffix(float a, type x, float b, type y, float c)\
{ \
return ValueTraits<type>::sum(x, y); \
} \
\
type ABI \
sum_many_##name##_##suffix( \
sum_many_##nameAndUnderscore##suffix( \
type a, type b, type c, type d, type e, type f, type g, type h, type i, \
type j, type k, type l, type m, type n, type o, type p, type q, type r) \
{ \
@ -84,8 +93,9 @@ sum_many_##name##_##suffix( \
}
#define ABI /* cdecl */
#define DEFINE_TYPE(x, y, z) FUNCTION_TESTS(x, y, z, cdecl)
#include "typedefs.h"
#define DEFINE_CDECL_FUNCTIONS(x, y, z) FUNCTION_TESTS(x##_, y, z, cdecl)
CTYPES_FOR_EACH_TYPE(DEFINE_CDECL_FUNCTIONS)
#undef DEFINE_CDECL_FUNCTIONS
#undef ABI
#if defined(_WIN32)
@ -98,13 +108,14 @@ test_void_t_stdcall()
}
#define ABI NS_STDCALL
#define DEFINE_TYPE(x, y, z) FUNCTION_TESTS(x, y, z, stdcall)
#include "typedefs.h"
#define DEFINE_STDCALL_FUNCTIONS(x, y, z) FUNCTION_TESTS(x##_, y, z, stdcall)
CTYPES_FOR_EACH_TYPE(DEFINE_STDCALL_FUNCTIONS)
#undef DEFINE_STDCALL_FUNCTIONS
#undef ABI
#endif /* defined(_WIN32) */
#define DEFINE_TYPE(name, type, ffiType) \
#define DEFINE_CDECL_TYPE_STATS(name, type, ffiType) \
struct align_##name { \
char x; \
type y; \
@ -127,7 +138,8 @@ get_##name##_stats(size_t* align, size_t* size, size_t* nalign, size_t* nsize, \
offsets[1] = offsetof(nested_##name, b); \
offsets[2] = offsetof(nested_##name, c); \
}
#include "typedefs.h"
CTYPES_FOR_EACH_TYPE(DEFINE_CDECL_TYPE_STATS)
#undef DEFINE_CDECL_TYPE_STATS
template <typename T>
int32_t StrLen(const T* string)

View File

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
#include "jspubtd.h"
#include "typedefs.h"
#define EXPORT_CDECL(type) MOZ_EXPORT type
#if defined(_WIN32)
@ -27,7 +28,7 @@ MOZ_BEGIN_EXTERN_C
EXPORT_CDECL(void*) get_voidptr_t_cdecl();
EXPORT_CDECL(void*) set_voidptr_t_cdecl(void*);
#define DEFINE_TYPE(name, type, ffiType) \
#define DECLARE_CDECL_FUNCTIONS(name, type, ffiType) \
EXPORT_CDECL(type) get_##name##_cdecl(); \
EXPORT_CDECL(type) set_##name##_cdecl(type); \
EXPORT_CDECL(type) sum_##name##_cdecl(type, type); \
@ -41,8 +42,8 @@ MOZ_BEGIN_EXTERN_C
EXPORT_CDECL(void) get_##name##_stats(size_t* align, size_t* size, \
size_t* nalign, size_t* nsize, \
size_t offsets[]);
#include "typedefs.h"
CTYPES_FOR_EACH_TYPE(DECLARE_CDECL_FUNCTIONS)
#undef DECLARE_CDECL_FUNCTIONS
#if defined(_WIN32)
EXPORT_STDCALL(void) test_void_t_stdcall();
@ -50,7 +51,7 @@ MOZ_BEGIN_EXTERN_C
EXPORT_STDCALL(void*) get_voidptr_t_stdcall();
EXPORT_STDCALL(void*) set_voidptr_t_stdcall(void*);
#define DEFINE_TYPE(name, type, ffiType) \
#define DECLARE_STDCALL_FUNCTIONS(name, type, ffiType) \
EXPORT_STDCALL(type) get_##name##_stdcall(); \
EXPORT_STDCALL(type) set_##name##_stdcall(type); \
EXPORT_STDCALL(type) sum_##name##_stdcall(type, type); \
@ -61,8 +62,8 @@ MOZ_BEGIN_EXTERN_C
EXPORT_STDCALL(type) sum_many_##name##_stdcall( \
type, type, type, type, type, type, type, type, type, \
type, type, type, type, type, type, type, type, type);
#include "typedefs.h"
CTYPES_FOR_EACH_TYPE(DECLARE_STDCALL_FUNCTIONS)
#undef DECLARE_STDCALL_FUNCTIONS
#endif /* defined(_WIN32) */