[llvm-commits] [PATCH][System] Add SwapByteOrder and move implementation from Support/MathExtras.h.
Michael Spencer
bigcheesegs at gmail.com
Wed Sep 15 16:44:44 PDT 2010
On Wed, Sep 15, 2010 at 6:50 PM, Chris Lattner <clattner at apple.com> wrote:
>
> On Sep 14, 2010, at 2:31 PM, Michael Spencer wrote:
>
>> On Tue, Sep 14, 2010 at 5:18 PM, Michael Spencer <bigcheesegs at gmail.com> wrote:
>>> The attached patch adds the SwapByteOrder function template to System.
>>> This patch is a
>>> prerequisite for the object file library I am writing.
>>>
>>> I want to replace the functions in MathExtras.h with SwapByteOrder
>>> because it is a generic implementation that makes it easier to write
>>> generic byte order independent code. This patch has no functionality
>>> changes.
>>>
>>> The optimized versions are platform dependent, and thus belong in System anyway.
>>>
>>> - Michael Spencer
>>>
>>
>> It had to happen eventually :(. Now the patch it attached.
>
> Hi Michael,
>
> What's wrong with the existing ByteSwap_XX functions? Why is a template better? Can you give an example of how this is better?
>
> Note that you're likely to run into problems on some systems (cygwin?) where uint32_t != unsigned.
>
> -Chris
If you look at the other patch I posted ([PATCH][Support] Add Endian.h
which contains generic code to deal with endian specific data) it is
used to byte swap an arbitrary integral type like so:
template<typename value_type, int host, int target>
static typename enable_if_c<host != target, value_type>::type
SwapByteOrderIfDifferent(value_type value) {
return sys::SwapByteOrder<value_type>(value);
}
Which is then used to directly read from memory (in this case a memory
mapped file):
template<endianness host_endianness>
struct endian_impl {
template<typename value_type>
static value_type read_le(const void *memory) {
return SwapByteOrderIfDifferent<value_type, host_endianness, little>(
*reinterpret_cast<const value_type *>(memory));
}
// other read and write functions.
};
Which is then used to create structs with "normal" looking members
that can directly reference memory mapped files:
template<typename value_type,
endianness target_endianness,
alignment target_alignment>
class packed_endian_specific_integral;
template<typename value_type>
class packed_endian_specific_integral<value_type, little, unaligned> {
public:
operator value_type() const {
return endian::read_le<value_type>(Value);
}
private:
uint8_t Value[sizeof(value_type)];
};
// Other specializations...
Which then have typedefs like:
typedef packed_endian_specific_integral<uint32_t, little, unaligned>
little_uint32_t;
As you can see, the value_type is defined a long way away from where
the byte swap occurs. SwapByteOrderIfDifferent could be specialized to
deal with the different value_types, but that belongs in System, and
is useful for others.
In short. It reduces the number of explicit template specializations
required, and therefore complexity.
And as for uint32_t != unsigned. Two things:
1) By unsigned you mean the the keyword unsigned, by itself. Like
"unsigned hey_look_im_a_var = 0;" right?
2) The ByteSwap_XX functions already have uintxx_t types, so I don't
see how that affects this code.
Thanks
- Michael Spencer
More information about the llvm-commits
mailing list