<div dir="ltr">A solution requiring no compiler support is to wrap the little endian values in a struct.<div><br></div><div>template<typename T></div><div>struct little_endian {</div><div>    little_endian(T value) : _value(value) {}<br>    T _value;</div><div>    T convert() { </div><div>       // conversion here</div><div>    }</div><div>};<br><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Nov 12, 2017 at 8:52 PM, Hal Finkel via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
On 11/12/2017 12:17 PM, Anatol Pomozov via cfe-dev wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hello<br>
<br>
On Sat, Nov 11, 2017 at 9:22 PM, Anatol Pomozov<br>
<<a href="mailto:anatol.pomozov@gmail.com" target="_blank">anatol.pomozov@gmail.com</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hello<br>
<br>
I am writing a code that deals with low-level PCI machinery. I need to<br>
read data from PCI config  MMIO. The data from device can be 8/16/32<br>
bits long and per specification it is little-endien. I have a set of<br>
macroses that convert from little-endien to CPU endieness. I have to<br>
use these macroses every time I access PCI config data. CPU endieness<br>
depends on CPU architecture and can be either little- or big-endien.<br>
<br>
I am looking for a way that helps me to detect errors when I access<br>
little-endien fields without proper conversion macros. I am thinking<br>
about following solution - have a marker macros called __le __be that<br>
tells compiler this field has specific endieness:<br>
<br>
struct virtio_net_hdr {<br>
     __le uint8_t flags;<br>
     __le uint8_t gso_type;<br>
     __le uint16_t hdr_len;<br>
     __le uint16_t gso_size;<br>
     __le uint16_t csum_start;<br>
     __le uint16_t csum_offset;<br>
};<br>
<br>
If we try to access the field as<br>
hdr->hdr_len = 20;<br>
<br>
then compiler should either:<br>
<br>
1) report an error and tell me that there is endieness mismatch<br>
between hdr->hdr_len and const '20'. The right way would be to use<br>
cpu_to_le() macro like:<br>
hdr->hdr_len = cpu_to_le(20);<br>
<br>
2) Or maybe compiler can completely automate conversion and call<br>
__builtin_bswap16()/__builtin_<wbr>bswap32/.. functions for us<br>
automatically?<br>
<br>
<br>
Is there any existing solution that does something similar. Quick<br>
googling did not give me anything useful. Could it be a part of core<br>
compiler functionality? Or as a third-party compiler plugin?<br>
</blockquote>
<br>
Actually instead of a marker macro it is better to have an attribute.<br>
It can be applied to a variable or struct. If applied to struct then<br>
all fields of the struct inherit the provided endianness. Here is a<br>
proposed example of usage<br>
<br>
__attribute__ ((endianness(little))) uint32_t pci_id;<br>
<br>
__attribute__ ((endianness(big))) struct arp_header {<br>
   uint16_t hw_type;<br>
   uint16_t proto_type;<br>
   uint8_t hw_len;<br>
   uint8_t proto_len;<br>
   ...<br>
}<br>
<br>
This attribute enables automatic byte swapping when accessing the fields.<br>
<br>
<br>
UPDATE: After more searching I found that GCC implements<br>
scalar_storage_order attribute [1]. I tested following example [2]<br>
with 7.1.0 and I see that gcc uses 'bswap' ASM instruction when<br>
accessing the struct fields. Yep that is exactly what I am looking<br>
for. But it seems the feature is not present in Clang. I wonder if<br>
Clang developers have plans to implement this feature.<br>
</blockquote>
<br></div></div>
If nothing else, please file a bug on <a href="http://bugs.llvm.org" rel="noreferrer" target="_blank">bugs.llvm.org</a> requesting the feature.<br>
<br>
 -Hal<span class="im HOEnZb"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<br>
[1] <a href="https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Common-Type-Attributes.html#Common-Type-Attributes" rel="noreferrer" target="_blank">https://gcc.gnu.org/onlinedocs<wbr>/gcc-7.2.0/gcc/Common-Type-<wbr>Attributes.html#Common-Type-<wbr>Attributes</a><br>
[2] <a href="https://stackoverflow.com/questions/45589653/does-g-support-scalar-storage-order" rel="noreferrer" target="_blank">https://stackoverflow.com/ques<wbr>tions/45589653/does-g-support-<wbr>scalar-storage-order</a><br>
______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</blockquote>
<br></span><span class="HOEnZb"><font color="#888888">
-- <br>
Hal Finkel<br>
Lead, Compiler Technology and Programming Languages<br>
Leadership Computing Facility<br>
Argonne National Laboratory</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div>