diff -r 024827a9db64 Modules/_ctypes/cfield.c --- a/Modules/_ctypes/cfield.c Fri Jun 24 20:52:27 2011 +0200 +++ b/Modules/_ctypes/cfield.c Sun Jul 10 12:26:32 2011 -0700 @@ -32,6 +32,47 @@ return (PyObject *)obj; } +/* Bitfield allocation strategies (allocation strategy is compiler specific) */ +#define ALLOCATION_STRATEGY_NATIVE 0 /* MSVC on Windows, GCC otherwise */ +#define ALLOCATION_STRATEGY_GCC 1 /* GCC */ +#define ALLOCATION_STRATEGY_MSVC 2 /* MSVC or GCC with -mms-bitfields flag */ + +/* Helper function to determine whether current bitfield can be continued based on allocation strategy */ +int +CanContinueField(int allocation_strategy, StgDictObject *dict, Py_ssize_t *pfield_size) +{ + switch (allocation_strategy) { + /* GCC can continue bitfield if requested size in bits is <= open field size */ + case ALLOCATION_STRATEGY_GCC: + return dict->size * 8 <= *pfield_size; + /* MSVC can continue bitfield if requested size in bits is == open field size */ + case ALLOCATION_STRATEGY_MSVC: + return dict->size * 8 == *pfield_size; + /* Should never reach this - inavlid argument */ + default: + assert(0); + return 0; + } +} + +/* Helper function to determine whether current bitfield can be expanded based on allocation strategy */ +int +CanExpandField(int allocation_strategy, StgDictObject *dict, Py_ssize_t *pfield_size) +{ + switch (allocation_strategy) { + /* GCC can expand bitfield if requested size in bits is >= open field size */ + case ALLOCATION_STRATEGY_GCC: + return dict->size * 8 >= *pfield_size; + /* MSVC never expands bitfield */ + case ALLOCATION_STRATEGY_MSVC: + return 0; + /* Should never reach this - invalid argument */ + default: + assert(0); + return 0; + } +} + /* * Expects the size, index and offset for the current field in *psize and * *poffset, stores the total size so far in *psize, the offset for the next @@ -62,6 +103,20 @@ #define CONT_BITFIELD 2 #define EXPAND_BITFIELD 3 + /* This variable will become argument once we have Python interface to set + * this flag. Currently we hardcode native strategy so code is functionally + * equivalent to what we had before. */ + int allocation_strategy = ALLOCATION_STRATEGY_NATIVE; + + /* Native is MSVC on Windows, GCC otherwise */ + if (allocation_strategy == ALLOCATION_STRATEGY_NATIVE) { +#ifdef MS_WIN32 + allocation_strategy = ALLOCATION_STRATEGY_MSVC; +#else + allocation_strategy = ALLOCATION_STRATEGY_GCC; +#endif + } + self = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL); if (self == NULL) @@ -75,24 +130,16 @@ } if (bitsize /* this is a bitfield request */ && *pfield_size /* we have a bitfield open */ -#ifdef MS_WIN32 - /* MSVC, GCC with -mms-bitfields */ - && dict->size * 8 == *pfield_size -#else - /* GCC */ - && dict->size * 8 <= *pfield_size -#endif + && CanContinueField(allocation_strategy, dict, pfield_size) && (*pbitofs + bitsize) <= *pfield_size) { /* continue bit field */ fieldtype = CONT_BITFIELD; -#ifndef MS_WIN32 } else if (bitsize /* this is a bitfield request */ && *pfield_size /* we have a bitfield open */ - && dict->size * 8 >= *pfield_size + && CanExpandField(allocation_strategy, dict, pfield_size) && (*pbitofs + bitsize) <= dict->size * 8) { /* expand bit field */ fieldtype = EXPAND_BITFIELD; -#endif } else if (bitsize) { /* start new bitfield */ fieldtype = NEW_BITFIELD;