Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #147185 > unrolled thread

Bit field usage

Started byjacobnavia <jacob@jacob.remcomp.fr>
First post2019-10-24 08:03 +0200
Last post2019-10-27 13:05 +0100
Articles 20 on this page of 65 — 15 participants

Back to article view | Back to comp.lang.c


Contents

  Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-24 08:03 +0200
    Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-24 10:15 -0600
      Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-24 18:55 +0200
        Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-24 21:28 -0600
      Re: Bit field usage scott@slp53.sl.home (Scott Lurndal) - 2019-10-24 17:22 +0000
        Re: Bit field usage Bonita Montero <Bonita.Montero@gmail.com> - 2019-10-24 19:45 +0200
          Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-24 19:59 +0200
            Re: Bit field usage Bonita Montero <Bonita.Montero@gmail.com> - 2019-10-24 20:02 +0200
              Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-24 21:29 -0600
                Re: Bit field usage Bonita Montero <Bonita.Montero@gmail.com> - 2019-10-25 07:51 +0200
                  Re: Bit field usage scott@slp53.sl.home (Scott Lurndal) - 2019-10-25 15:05 +0000
          Re: Bit field usage Bart <bc@freeuk.com> - 2019-10-24 19:13 +0100
            Re: Bit field usage Bonita Montero <Bonita.Montero@gmail.com> - 2019-10-24 20:54 +0200
              Re: Bit field usage Bart <bc@freeuk.com> - 2019-10-24 20:12 +0100
                Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-10-24 23:03 +0200
                  Re: Bit field usage Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-24 22:50 +0100
                    Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-10-25 09:18 +0200
                      Re: Bit field usage Reinhardt Behm <rbehm@hushmail.com> - 2019-10-25 15:46 +0800
                      Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-26 12:36 -0500
                  Re: Bit field usage scott@slp53.sl.home (Scott Lurndal) - 2019-10-25 15:04 +0000
                    Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-26 12:40 -0500
                  Re: Bit field usage Philipp Klaus Krause <pkk@spth.de> - 2019-10-26 21:12 +0200
                Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-25 09:25 -0600
                  Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-26 12:52 -0500
        Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-24 19:56 +0200
          Re: Bit field usage already5chosen@yahoo.com - 2019-10-24 12:03 -0700
            Re: Bit field usage scott@slp53.sl.home (Scott Lurndal) - 2019-10-24 19:40 +0000
              Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-24 22:15 +0200
              Re: Bit field usage already5chosen@yahoo.com - 2019-10-24 14:16 -0700
      Re: Bit field usage Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-10-24 17:50 -0700
        Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-25 09:36 -0600
          Re: Bit field usage Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-10-27 04:54 -0700
            Re: Bit field usage Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-10-27 10:05 -0600
    Re: Bit field usage Philipp Klaus Krause <pkk@spth.de> - 2019-10-26 20:15 +0200
      Re: Bit field usage Philipp Klaus Krause <pkk@spth.de> - 2019-10-26 20:16 +0200
        Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-26 20:37 +0200
          Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-26 13:41 -0500
            Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-26 21:54 +0200
              Re: Bit field usage already5chosen@yahoo.com - 2019-10-27 03:46 -0700
                Re: Bit field usage jacobnavia <jacob@jacob.remcomp.fr> - 2019-10-27 12:50 +0100
                  Re: Bit field usage already5chosen@yahoo.com - 2019-10-27 06:37 -0700
                Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-10-27 13:00 +0100
                  Re: Bit field usage already5chosen@yahoo.com - 2019-10-27 07:19 -0700
                    Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-10-27 22:30 +0100
                      Re: Bit field usage Christopher Collins <ccollins476ad@gmail.com> - 2019-11-07 12:36 -0800
                        Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-11-08 08:18 +0100
                          Re: Bit field usage Christopher Collins <ccollins476ad@gmail.com> - 2019-11-08 10:19 -0800
                            Re: Bit field usage Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-11-08 21:47 +0000
                            Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-11-10 14:08 +0100
                              Re: Bit field usage Christopher Collins <ccollins476ad@gmail.com> - 2019-11-11 09:26 -0800
                                Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-11-11 20:31 +0100
                                  Re: Bit field usage Christopher Collins <ccollins476ad@gmail.com> - 2019-11-11 23:01 -0800
                                    Re: Bit field usage Christopher Collins <ccollins476ad@gmail.com> - 2019-11-11 23:25 -0800
                                    Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-11-12 10:54 +0100
                                      Re: Bit field usage Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-11-12 14:43 +0000
                                        Re: Bit field usage James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-11-12 10:54 -0500
                                          Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-11-12 19:37 +0100
                Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-27 08:36 -0500
                  Re: Bit field usage already5chosen@yahoo.com - 2019-10-27 06:49 -0700
              Re: Bit field usage Bonita Montero <Bonita.Montero@gmail.com> - 2019-10-27 14:23 +0100
              Re: Bit field usage Robert Wessel <robertwessel2@yahoo.com> - 2019-10-27 08:42 -0500
          Re: Bit field usage Philipp Klaus Krause <pkk@spth.de> - 2019-10-26 21:06 +0200
          Re: Bit field usage Bart <bc@freeuk.com> - 2019-10-26 20:41 +0100
            Re: Bit field usage Philipp Klaus Krause <pkk@spth.de> - 2019-10-27 08:29 +0100
              Re: Bit field usage David Brown <david.brown@hesbynett.no> - 2019-10-27 13:05 +0100

Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →


#147288

Fromalready5chosen@yahoo.com
Date2019-10-27 06:37 -0700
Message-ID<ecf96188-d642-4211-a738-ddd98fdaf6bb@googlegroups.com>
In reply to#147281
On Sunday, October 27, 2019 at 1:50:57 PM UTC+2, jacobnavia wrote:
> Le 27/10/2019 à 11:46, already5chosen@yahoo.com a écrit :
> >   ARM/ARM64 and POWER. ARM has no alignment requirements on the integer side of the ISA.
> 
> Here are the relevant pages of the ARM64 Architecture manual
> 
> <quote>
> B2.4.2 Alignment of data accesses
> An unaligned access to any type of Device memory causes an Alignment fault.
> The alignment requirements for accesses to Normal memory are as follows:
> • For all instructions that load or store a single or multiple 
> registers, other than Load-Exclusive/Store-Exclusive and 
> Load-Acquire/Store-Release, if the address that is accessed is not
> aligned to the size of the data element being accessed, then one of the 
> following occurs:
> — An Alignment fault is generated.
> — An unaligned access is performed.
> 
> SCTLR_ELx.A at the current Exception level can be configured to enable 
> an alignment check, and thereby determine which of these two options is 
> used.
> Note
> — The SCTLR_EL1.A bit that is applicable to software running at EL0, can 
> only be accessed from EL1
> or above.
> — Alignment checks are based on element size, not overall access size. 
> This affects SIMD element and structure loads and stores, and also 
> Load/Store pair instructions.
> • For all Load-Exclusive/Store-Exclusive and Load-Acquire/Store-Release 
> memory accesses that access a single element or a pair of elements, an 
> alignment fault is generated if the address being accessed is not
> aligned to the size of the data structure being accessed.
> A failed alignment check results in an Alignment fault, which is taken 
> as a Data Abort exception. These exceptions are taken at the lowest 
> Exception level that can handle the exception, consistent with the basic 
> requirement that the Exception level never decreases on an exception.
> 
> B2.4.3 Unaligned data access restrictions
> • Accesses are not guaranteed to be single-copy atomic except at the 
> byte access level.
> • Unaligned accesses typically takes a number of additional cycles to 
> complete compared to a naturally-aligned access.

That's part is not true on high-performance ARMv8A cores, like last 4-5 generation of Apple's Axx or Cortex-A76.
Typically, i.e. as long as there is no page crossing, the cost of unaligned accesses is at worst the same as o 2 aligned accesses, but often less than that.

> • An operation that performs an unaligned access can abort on any memory 
> access that it makes, and can abort on more than one access. This means 
> that an unaligned access that occurs across a page boundary can
> generate an abort on either side of the boundary.

That's not different from x86, except that on x86 it's called 'fault' rather than 'abort'.

> </end quote>
> 
> The situation is not really as you describe it. Alignment still is 
> important for many operations and can't be dismissed. That is why the 
> compilers will always align the data at its natural boundaries.

In practice that's exactly the same as x86-64. On both platforms non-aligned accesses work fine and fast, but not guaranteed to be atomic.
ARM's ability to throw exception on non-SIMD unaligned access can be useful for debugging/tuning, but there are no reasons to use it for release builds.

[toc] | [prev] | [next] | [standalone]


#147283

FromDavid Brown <david.brown@hesbynett.no>
Date2019-10-27 13:00 +0100
Message-ID<qp40s8$pvs$1@dont-email.me>
In reply to#147279
On 27/10/2019 11:46, already5chosen@yahoo.com wrote:
> On Saturday, October 26, 2019 at 10:54:34 PM UTC+3, jacobnavia
> wrote:
>> Le 26/10/2019 à 20:41, Robert Wessel a écrit :
>>> That is not true of all 64-bit implementations, of course.
>>> Consider MSVC invoked with /Zp1.  Of course it's true of many
>>> implementations.
>> 
>> Yes, packing fields would be possible in processors like the x86.
>> It is not possible in RISC processors where alignment is much
>> stricter.
> 
> There are only 2 high-performance RISCs that are still relevant for
> new development: ARM/ARM64 and POWER. ARM has no alignment
> requirements on the integer side of the ISA. The same for Power in
> Big Endian mode. As far as I remember, Power operating in Little
> Endian mode used to have alignment requirements, but it seems that
> since Power8 they have "pure little-endian" mode that removes these
> limitations.
> 

There are many, many other RISC ISA's that are in heavy use - the world 
does /not/ revolve around the fastest cores.  And for lots of ISA's, 
alignment is strict.

Even for ISA's that sometimes allow unaligned access, it can often 
depend on the implementation.  Some ARM core implementations support 
unaligned access, others do not, others support it only for certain 
instructions.  The same applies to PPC (I don't know the details of 
Power).  Almost all ISA's (including x86) fail on unaligned access for 
certain kinds of accesses - typically atomic or lock instructions, 
vector instructions, load/store multiple instructions, etc.  And for 
many devices, unaligned access can be very much slower than aligned access.

[toc] | [prev] | [next] | [standalone]


#147291

Fromalready5chosen@yahoo.com
Date2019-10-27 07:19 -0700
Message-ID<95febac6-81a6-490b-9197-36c3b1ae5811@googlegroups.com>
In reply to#147283
On Sunday, October 27, 2019 at 2:00:17 PM UTC+2, David Brown wrote:
> On 27/10/2019 11:46, already5chosen@yahoo.com wrote:
> > On Saturday, October 26, 2019 at 10:54:34 PM UTC+3, jacobnavia
> > wrote:
> >> Le 26/10/2019 à 20:41, Robert Wessel a écrit :
> >>> That is not true of all 64-bit implementations, of course.
> >>> Consider MSVC invoked with /Zp1.  Of course it's true of many
> >>> implementations.
> >> 
> >> Yes, packing fields would be possible in processors like the x86.
> >> It is not possible in RISC processors where alignment is much
> >> stricter.
> > 
> > There are only 2 high-performance RISCs that are still relevant for
> > new development: ARM/ARM64 and POWER. ARM has no alignment
> > requirements on the integer side of the ISA. The same for Power in
> > Big Endian mode. As far as I remember, Power operating in Little
> > Endian mode used to have alignment requirements, but it seems that
> > since Power8 they have "pure little-endian" mode that removes these
> > limitations.
> > 
> 
> There are many, many other RISC ISA's that are in heavy use - the world 
> does /not/ revolve around the fastest cores.  And for lots of ISA's, 
> alignment is strict.
> 
> Even for ISA's that sometimes allow unaligned access, it can often 
> depend on the implementation.  Some ARM core implementations support 
> unaligned access, others do not, others support it only for certain 
> instructions. 

IIRC, under ARMv7 or later support for unaligned accesses is mandatory.
Of course, only for "normal' memory, I/O is different and implementation-dependent, as it should be.

> The same applies to PPC (I don't know the details of 
> Power).  Almost all ISA's (including x86) fail on unaligned access for 
> certain kinds of accesses - typically atomic or lock instructions, 
> vector instructions, load/store multiple instructions, etc.  And for 
> many devices, unaligned access can be very much slower than aligned access.

Atomics can't remain atomic, that's obvious. They don't have to fail, but as long as they don't do what they are intended to do it's of little importance.
As to vectors, the trend here is certainly toward relaxation or removal of alignment restrictions.

[toc] | [prev] | [next] | [standalone]


#147296

FromDavid Brown <david.brown@hesbynett.no>
Date2019-10-27 22:30 +0100
Message-ID<qp529j$eep$1@dont-email.me>
In reply to#147291
On 27/10/2019 15:19, already5chosen@yahoo.com wrote:
> On Sunday, October 27, 2019 at 2:00:17 PM UTC+2, David Brown wrote:
>> On 27/10/2019 11:46, already5chosen@yahoo.com wrote:
>>> On Saturday, October 26, 2019 at 10:54:34 PM UTC+3, jacobnavia 
>>> wrote:
>>>> Le 26/10/2019 à 20:41, Robert Wessel a écrit :
>>>>> That is not true of all 64-bit implementations, of course. 
>>>>> Consider MSVC invoked with /Zp1.  Of course it's true of
>>>>> many implementations.
>>>> 
>>>> Yes, packing fields would be possible in processors like the
>>>> x86. It is not possible in RISC processors where alignment is
>>>> much stricter.
>>> 
>>> There are only 2 high-performance RISCs that are still relevant
>>> for new development: ARM/ARM64 and POWER. ARM has no alignment 
>>> requirements on the integer side of the ISA. The same for Power
>>> in Big Endian mode. As far as I remember, Power operating in
>>> Little Endian mode used to have alignment requirements, but it
>>> seems that since Power8 they have "pure little-endian" mode that
>>> removes these limitations.
>>> 
>> 
>> There are many, many other RISC ISA's that are in heavy use - the
>> world does /not/ revolve around the fastest cores.  And for lots of
>> ISA's, alignment is strict.
>> 
>> Even for ISA's that sometimes allow unaligned access, it can often 
>> depend on the implementation.  Some ARM core implementations
>> support unaligned access, others do not, others support it only for
>> certain instructions.
> 
> IIRC, under ARMv7 or later support for unaligned accesses is
> mandatory. Of course, only for "normal' memory, I/O is different and
> implementation-dependent, as it should be.
> 
>> The same applies to PPC (I don't know the details of Power).
>> Almost all ISA's (including x86) fail on unaligned access for 
>> certain kinds of accesses - typically atomic or lock instructions, 
>> vector instructions, load/store multiple instructions, etc.  And
>> for many devices, unaligned access can be very much slower than
>> aligned access.
> 
> Atomics can't remain atomic, that's obvious. They don't have to fail,
> but as long as they don't do what they are intended to do it's of
> little importance. As to vectors, the trend here is certainly toward
> relaxation or removal of alignment restrictions.
> 

I don't believe there is any such trend towards removing or relaxing 
alignment restrictions.  I can't claim to have followed cpu details 
closely enough to be confident in that belief, but I certainly don't see 
any benefit in having that trend.  There are rarely any advantages in 
having non-aligned data, and you usually have to go out of your way to 
create it in the first place (often invoking undefined behaviour) - 
while there are good hardware efficiency reasons for wanting alignment.

For vector instructions, it is not always clear what is meant by 
"aligned" access.  If you have a vector of 4 4-byte integers, for 
example, it can be convenient for the programmer if the alignment 
requirements are 4 byte alignment rather than 16 byte alignment.  But 
there is little to be gained for the programmer by allowing 1 byte 
alignment access.

It seems to me that regardless of whether or not a particular cpu 
implementation supports unaligned access or not, that it is almost 
always best to stick to the alignment specified by the ABI and handled 
automatically by the compiler.

[toc] | [prev] | [next] | [standalone]


#147747

FromChristopher Collins <ccollins476ad@gmail.com>
Date2019-11-07 12:36 -0800
Message-ID<slrnqs901k.s72.ccollins476ad@pseudoephedrine.nightmare-heaven.no-ip.biz>
In reply to#147296
On 2019-10-27, David Brown <david.brown@hesbynett.no> wrote:
> I don't believe there is any such trend towards removing or relaxing 
> alignment restrictions.  I can't claim to have followed cpu details 
> closely enough to be confident in that belief, but I certainly don't see 
> any benefit in having that trend.  There are rarely any advantages in 
> having non-aligned data, and you usually have to go out of your way to 
> create it in the first place (often invoking undefined behaviour) - 
> while there are good hardware efficiency reasons for wanting alignment.

I disagree with the claim that there is rarely any advantage in having
unaligned data.  Combined with packed structs, support for unaligned
access can result in a considerable code size reduction.  I included a
simple demonstration in an earlier post:
<https://groups.google.com/d/msg/comp.lang.c++/a5xVfaw1y08/IdcvfGNbFQAJ>.

Chris

[toc] | [prev] | [next] | [standalone]


#147759

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-08 08:18 +0100
Message-ID<qq34rd$v8u$1@dont-email.me>
In reply to#147747
On 07/11/2019 21:36, Christopher Collins wrote:
> On 2019-10-27, David Brown <david.brown@hesbynett.no> wrote:
>> I don't believe there is any such trend towards removing or relaxing
>> alignment restrictions.  I can't claim to have followed cpu details
>> closely enough to be confident in that belief, but I certainly don't see
>> any benefit in having that trend.  There are rarely any advantages in
>> having non-aligned data, and you usually have to go out of your way to
>> create it in the first place (often invoking undefined behaviour) -
>> while there are good hardware efficiency reasons for wanting alignment.
> 
> I disagree with the claim that there is rarely any advantage in having
> unaligned data.  Combined with packed structs, support for unaligned
> access can result in a considerable code size reduction.  I included a
> simple demonstration in an earlier post:
> <https://groups.google.com/d/msg/comp.lang.c++/a5xVfaw1y08/IdcvfGNbFQAJ>.
> 

I don't remember the details of that thread, but it looks like you are 
trying to find an efficient way to copy a packed struct into a byte 
buffer.  The quotation from my own post was:

 > Write your code properly and safely (using shifts and masks, memcpy, or
 > compiler-specific features or intrinsics) and let the compiler turn it
 > into unaligned accesses.  Writing safe, correct, and valid source code
 > is the programmer's responsibility.  Turning it into small and fast
 > object code is the compiler's responsibility.  Don't try to do the
 > compiler's job - work with it so that it can to the best job it can.

I stand by that advice.  By using the compiler-specific "packed" struct 
feature (most compilers have an equivalent, but the details are specific 
to the compiler) it is then safe to use a "memcpy" for a short marshal 
function.  And if you also use the "align" attribute (or C11 _Alignas), 
the compiler can do the copying using aligned 32 bit accesses rather 
than unaligned accesses, for greater speed.

Unaligned accesses are not a benefit here - aligned would have worked 
better.

[toc] | [prev] | [next] | [standalone]


#147793

FromChristopher Collins <ccollins476ad@gmail.com>
Date2019-11-08 10:19 -0800
Message-ID<slrnqsbcdc.s72.ccollins476ad@pseudoephedrine.nightmare-heaven.no-ip.biz>
In reply to#147759
On 2019-11-08, David Brown <david.brown@hesbynett.no> wrote:
> On 07/11/2019 21:36, Christopher Collins wrote:
>> I disagree with the claim that there is rarely any advantage in having
>> unaligned data.  Combined with packed structs, support for unaligned
>> access can result in a considerable code size reduction.  I included a
>> simple demonstration in an earlier post:
>> <https://groups.google.com/d/msg/comp.lang.c++/a5xVfaw1y08/IdcvfGNbFQAJ>.
>> 
>
> I don't remember the details of that thread, but it looks like you are 
> trying to find an efficient way to copy a packed struct into a byte 
> buffer.  The quotation from my own post was:
>
> > Write your code properly and safely (using shifts and masks, memcpy, or
> > compiler-specific features or intrinsics) and let the compiler turn it
> > into unaligned accesses.  Writing safe, correct, and valid source code
> > is the programmer's responsibility.  Turning it into small and fast
> > object code is the compiler's responsibility.  Don't try to do the
> > compiler's job - work with it so that it can to the best job it can.
>
> I stand by that advice.  By using the compiler-specific "packed" struct 
> feature (most compilers have an equivalent, but the details are specific 
> to the compiler) it is then safe to use a "memcpy" for a short marshal 
> function.  And if you also use the "align" attribute (or C11 _Alignas), 
> the compiler can do the copying using aligned 32 bit accesses rather 
> than unaligned accesses, for greater speed.
>
> Unaligned accesses are not a benefit here - aligned would have worked 
> better.

You can't always arrange for aligned data.  Take a networking stack for
example.  You need functions to parse and strip headers from the front
of a buffer.  Unless each header is sized according to the alignment
requirements of the processor, the buffer won't remain aligned
throughout this process.

The reverse process, prepending headers to outgoing data, has the same
characteristics.

I used to eschew packed structs as nonstandard and of little practical
use.  Then we tried using them in a Bluetooth stack implementation and
the reduction in code size was dramatic (sorry, I don't have numbers).
I believe there is simply no way to achieve the same reduction in code
size without using packed structs (on architectures that support
unaligned access).

Chris

[toc] | [prev] | [next] | [standalone]


#147801

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-11-08 21:47 +0000
Message-ID<slrnqsbojj.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#147793
On Fri, 2019-11-08, Christopher Collins wrote:
> On 2019-11-08, David Brown <david.brown@hesbynett.no> wrote:
>> On 07/11/2019 21:36, Christopher Collins wrote:
>>> I disagree with the claim that there is rarely any advantage in having
>>> unaligned data.  Combined with packed structs, support for unaligned
>>> access can result in a considerable code size reduction.  I included a
>>> simple demonstration in an earlier post:
>>> <https://groups.google.com/d/msg/comp.lang.c++/a5xVfaw1y08/IdcvfGNbFQAJ>.
>>> 
>>
>> I don't remember the details of that thread, but it looks like you are 
>> trying to find an efficient way to copy a packed struct into a byte 
>> buffer.  The quotation from my own post was:
>>
>> > Write your code properly and safely (using shifts and masks, memcpy, or
>> > compiler-specific features or intrinsics) and let the compiler turn it
>> > into unaligned accesses.  Writing safe, correct, and valid source code
>> > is the programmer's responsibility.  Turning it into small and fast
>> > object code is the compiler's responsibility.  Don't try to do the
>> > compiler's job - work with it so that it can to the best job it can.
>>
>> I stand by that advice.  By using the compiler-specific "packed" struct 
>> feature (most compilers have an equivalent, but the details are specific 
>> to the compiler) it is then safe to use a "memcpy" for a short marshal 
>> function.  And if you also use the "align" attribute (or C11 _Alignas), 
>> the compiler can do the copying using aligned 32 bit accesses rather 
>> than unaligned accesses, for greater speed.
>>
>> Unaligned accesses are not a benefit here - aligned would have worked 
>> better.
>
> You can't always arrange for aligned data.  Take a networking stack for
> example.  You need functions to parse and strip headers from the front
> of a buffer.  Unless each header is sized according to the alignment
> requirements of the processor, the buffer won't remain aligned
> throughout this process.
>
> The reverse process, prepending headers to outgoing data, has the same
> characteristics.
>
> I used to eschew packed structs as nonstandard and of little practical
> use.  Then we tried using them in a Bluetooth stack implementation and
> the reduction in code size was dramatic (sorry, I don't have numbers).

I find that hard to believe: few programs have an infinite number of
data structures to (de)serialise, and the code for each would be quite
small.  The code size is proportional to the size of the protocol
specification.

Or rather: I don't find it hard to believe that using packed structs
can result in less object code, I just find it hard to believe it
often matters.

Maybe you had a tiny budget for program memory? I don't do tiny
embedded systems much, and don't worry about, say, a few dozen
kilobytes extra.

Or maybe excessive inlining (like gcc -O3) inflated the numbers?

> I believe there is simply no way to achieve the same reduction in code
> size without using packed structs (on architectures that support
> unaligned access).
>
> Chris

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#147875

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-10 14:08 +0100
Message-ID<qq9251$aej$1@dont-email.me>
In reply to#147793
On 08/11/2019 19:19, Christopher Collins wrote:
> On 2019-11-08, David Brown <david.brown@hesbynett.no> wrote:
>> On 07/11/2019 21:36, Christopher Collins wrote:
>>> I disagree with the claim that there is rarely any advantage in having
>>> unaligned data.  Combined with packed structs, support for unaligned
>>> access can result in a considerable code size reduction.  I included a
>>> simple demonstration in an earlier post:
>>> <https://groups.google.com/d/msg/comp.lang.c++/a5xVfaw1y08/IdcvfGNbFQAJ>.
>>>
>>
>> I don't remember the details of that thread, but it looks like you are
>> trying to find an efficient way to copy a packed struct into a byte
>> buffer.  The quotation from my own post was:
>>
>>> Write your code properly and safely (using shifts and masks, memcpy, or
>>> compiler-specific features or intrinsics) and let the compiler turn it
>>> into unaligned accesses.  Writing safe, correct, and valid source code
>>> is the programmer's responsibility.  Turning it into small and fast
>>> object code is the compiler's responsibility.  Don't try to do the
>>> compiler's job - work with it so that it can to the best job it can.
>>
>> I stand by that advice.  By using the compiler-specific "packed" struct
>> feature (most compilers have an equivalent, but the details are specific
>> to the compiler) it is then safe to use a "memcpy" for a short marshal
>> function.  And if you also use the "align" attribute (or C11 _Alignas),
>> the compiler can do the copying using aligned 32 bit accesses rather
>> than unaligned accesses, for greater speed.
>>
>> Unaligned accesses are not a benefit here - aligned would have worked
>> better.
> 
> You can't always arrange for aligned data.  Take a networking stack for
> example.  You need functions to parse and strip headers from the front
> of a buffer.  Unless each header is sized according to the alignment
> requirements of the processor, the buffer won't remain aligned
> throughout this process.
> 
> The reverse process, prepending headers to outgoing data, has the same
> characteristics.

I said that unaligned accesses were not a benefit in this case, not that 
they are never useful.

> 
> I used to eschew packed structs as nonstandard and of little practical
> use.  Then we tried using them in a Bluetooth stack implementation and
> the reduction in code size was dramatic (sorry, I don't have numbers).
> I believe there is simply no way to achieve the same reduction in code
> size without using packed structs (on architectures that support
> unaligned access).
> 

You are wrong - but only if you have a good enough compiler, use the 
right options, and write your code in a way that the compiler recognises 
and optimises.  It is entirely possible for a compiler to optimise 
memcpy or byte-by-byte access into unaligned word access if the target 
supports it, and it certainly happens in some cases.  But it won't 
happen in all cases, and if efficiency matters you'll have to check the 
generated output.

I don't see much use of packed structs.  But that does not mean they are 
not useful on occasion.

[toc] | [prev] | [next] | [standalone]


#147940

FromChristopher Collins <ccollins476ad@gmail.com>
Date2019-11-11 09:26 -0800
Message-ID<slrnqsj6dd.ih3.ccollins476ad@pseudoephedrine.nightmare-heaven.no-ip.biz>
In reply to#147875
On 2019-11-10, David Brown <david.brown@hesbynett.no> wrote:
> On 08/11/2019 19:19, Christopher Collins wrote:
>> You can't always arrange for aligned data.  Take a networking stack for
>> example.  You need functions to parse and strip headers from the front
>> of a buffer.  Unless each header is sized according to the alignment
>> requirements of the processor, the buffer won't remain aligned
>> throughout this process.
>> 
>> The reverse process, prepending headers to outgoing data, has the same
>> characteristics.
>
> I said that unaligned accesses were not a benefit in this case, not that 
> they are never useful.

This is what you said:

    There are rarely any advantages in having non-aligned data, and you
    usually have to go out of your way to create it in the first place
    (often invoking undefined behaviour) - while there are good hardware
    efficiency reasons for wanting alignment.

To me, this sounds like you object to using unaligned data except in
very special circumstances.  I disagree, but perhaps I am misreading
your argument.

>> I used to eschew packed structs as nonstandard and of little practical
>> use.  Then we tried using them in a Bluetooth stack implementation and
>> the reduction in code size was dramatic (sorry, I don't have numbers).
>> I believe there is simply no way to achieve the same reduction in code
>> size without using packed structs (on architectures that support
>> unaligned access).
>> 
>
> You are wrong - but only if you have a good enough compiler, use the 
> right options, and write your code in a way that the compiler recognises 
> and optimises.  It is entirely possible for a compiler to optimise 
> memcpy or byte-by-byte access into unaligned word access if the target 
> supports it, and it certainly happens in some cases.  But it won't 
> happen in all cases, and if efficiency matters you'll have to check the 
> generated output.

Do you know of a compiler that does that?  (Honest question).  From the
godbolt example I posted, it seems gcc with -Os does not.  In theory,
compilers could do all sorts of optimizations.  That doesn't help
someone meet a project's requirements.

> I don't see much use of packed structs.  But that does not mean they are 
> not useful on occasion.

In addition to reduced code size, packed structs also simplify code.
Rather than needing to implement unmarshalling code for every header and
command in a stack, you simply do this:

    struct foo_header *hdr = (struct foo_header *)buf;

and you have a header ready to be processed.

[toc] | [prev] | [next] | [standalone]


#147944

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-11 20:31 +0100
Message-ID<qqccum$lt5$1@dont-email.me>
In reply to#147940
On 11/11/2019 18:26, Christopher Collins wrote:
> On 2019-11-10, David Brown <david.brown@hesbynett.no> wrote:
>> On 08/11/2019 19:19, Christopher Collins wrote:
>>> You can't always arrange for aligned data.  Take a networking stack for
>>> example.  You need functions to parse and strip headers from the front
>>> of a buffer.  Unless each header is sized according to the alignment
>>> requirements of the processor, the buffer won't remain aligned
>>> throughout this process.
>>>
>>> The reverse process, prepending headers to outgoing data, has the same
>>> characteristics.
>>
>> I said that unaligned accesses were not a benefit in this case, not that
>> they are never useful.
> 
> This is what you said:
> 
>      There are rarely any advantages in having non-aligned data, and you
>      usually have to go out of your way to create it in the first place
>      (often invoking undefined behaviour) - while there are good hardware
>      efficiency reasons for wanting alignment.
> 
> To me, this sounds like you object to using unaligned data except in
> very special circumstances.  I disagree, but perhaps I am misreading
> your argument.

No, that is a reasonable summary of what I said.  There /are/ times when 
unaligned accesses are the best solution (noting that "best" depends on 
the requirements, and can be very subjective) - but I don't think it 
happens often.  And even then, I think it is better to let the compiler 
deal with it rather than manually accessing data at non-aligned 
addresses.  It's fine if the compiler turns a memcpy() of 4 bytes into a 
single word read - much less fine if the programmer casts a char* or 
void* pointer to an int* in order to access the non-aligned data.

Similarly, /sometimes/ packed structs are a convenient solution - but 
not often.

> 
>>> I used to eschew packed structs as nonstandard and of little practical
>>> use.  Then we tried using them in a Bluetooth stack implementation and
>>> the reduction in code size was dramatic (sorry, I don't have numbers).
>>> I believe there is simply no way to achieve the same reduction in code
>>> size without using packed structs (on architectures that support
>>> unaligned access).
>>>
>>
>> You are wrong - but only if you have a good enough compiler, use the
>> right options, and write your code in a way that the compiler recognises
>> and optimises.  It is entirely possible for a compiler to optimise
>> memcpy or byte-by-byte access into unaligned word access if the target
>> supports it, and it certainly happens in some cases.  But it won't
>> happen in all cases, and if efficiency matters you'll have to check the
>> generated output.
> 
> Do you know of a compiler that does that?  (Honest question).  From the
> godbolt example I posted, it seems gcc with -Os does not.  In theory,
> compilers could do all sorts of optimizations.  That doesn't help
> someone meet a project's requirements.

 From the example you posted, gcc /does/ do exactly that.  You wrote 
"memcpy(&out[1], &m->b, 4);", and the compiler generated "ldr r3, [r0, 
#1]" "str r3, [r1, #1]".

When you already have the packed struct, it makes more sense to do a 
single memcpy() rather than several individual memcpy's turned into 
unaligned accesses.  But the compiler is clearly optimising the memcpy's 
into larger (potentially) unaligned accesses.

> 
>> I don't see much use of packed structs.  But that does not mean they are
>> not useful on occasion.
> 
> In addition to reduced code size, packed structs also simplify code.

Your code was not really doing marshalling, despite the name of the 
functions, since it was just a straight copy.

Usually when you are reading in the header for data coming in from 
outside (on the network, or in a file), you are doing lots of work on it 
anyway - checking for validity, in particular.  And usually much of the 
header will be used only at that point.  You often don't need to store 
it, and you don't need to access the fields.

But sure, on the occasions when packed structs really help, use them.

> Rather than needing to implement unmarshalling code for every header and
> command in a stack, you simply do this:
> 
>      struct foo_header *hdr = (struct foo_header *)buf;
> 
> and you have a header ready to be processed.
> 

Except that you don't - you have to be careful with casting pointer 
types, or fall foul of aliasing rules.  If you are doing a lot of this 
kind of thing, you might like to add:

#pragma GCC optimize("-fno-strict-aliasing")

and then the cast is safe (on gcc or clang).

[toc] | [prev] | [next] | [standalone]


#147947

FromChristopher Collins <ccollins476ad@gmail.com>
Date2019-11-11 23:01 -0800
Message-ID<slrnqskm5n.ih3.ccollins476ad@pseudoephedrine.nightmare-heaven.no-ip.biz>
In reply to#147944
On 2019-11-11, David Brown <david.brown@hesbynett.no> wrote:
> On 11/11/2019 18:26, Christopher Collins wrote:
>> Rather than needing to implement unmarshalling code for every header and
>> command in a stack, you simply do this:
>> 
>>      struct foo_header *hdr = (struct foo_header *)buf;
>> 
>> and you have a header ready to be processed.
>> 
>
> Except that you don't - you have to be careful with casting pointer 
> types, or fall foul of aliasing rules.  If you are doing a lot of this 
> kind of thing, you might like to add:
>
> #pragma GCC optimize("-fno-strict-aliasing")
>
> and then the cast is safe (on gcc or clang).

I'm not sure that's true, but I'll admit that I'm not terribly familiar
with the C spec.  I tried this test with gcc 9.2.0:

    $ cat aliasing.c
    struct s {
        char c;
        int i;
    };

    void dosomething(struct s *s);

    int main(void) {
        unsigned char cbuf[100] = { 0 };
        float fbuf[100] = { 0 };

        struct s *s0 = (struct s *)(cbuf + 7);
        struct s *s1 = (struct s *)(fbuf + 7);

        dosomething(s0);
        dosomething(s1);
    }

    $ gcc -O2 -Wall -fstrict-aliasing -Wstrict-aliasing=1 -pedantic-errors aliasing.c
    aliasing.c: In function 'main':
    aliasing.c:11:38: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
       11 |     struct s s1 = *(struct s *)(fbuf + 7);
          |                                ~~~~~~^~~~

(plus a linker error due to `dosomething` being undefined)

It warns about the float array, not the unsigned char.  If casting a
char buffer to a pointer-to-struct is undefined without an additional
attribute or compiler option then that would be good to know.

In any case, I feel like I've said my piece as best I could.

Chris

[toc] | [prev] | [next] | [standalone]


#147948

FromChristopher Collins <ccollins476ad@gmail.com>
Date2019-11-11 23:25 -0800
Message-ID<slrnqsknid.ih3.ccollins476ad@pseudoephedrine.nightmare-heaven.no-ip.biz>
In reply to#147947
On 2019-11-12, Christopher Collins <ccollins476ad@gmail.com> wrote:
> On 2019-11-11, David Brown <david.brown@hesbynett.no> wrote:
>> On 11/11/2019 18:26, Christopher Collins wrote:
>>> Rather than needing to implement unmarshalling code for every header and
>>> command in a stack, you simply do this:
>>> 
>>>      struct foo_header *hdr = (struct foo_header *)buf;
>>> 
>>> and you have a header ready to be processed.
>>> 
>>
>> Except that you don't - you have to be careful with casting pointer 
>> types, or fall foul of aliasing rules.  If you are doing a lot of this 
>> kind of thing, you might like to add:
>>
>> #pragma GCC optimize("-fno-strict-aliasing")
>>
>> and then the cast is safe (on gcc or clang).
>
> I'm not sure that's true, but I'll admit that I'm not terribly familiar
> with the C spec.  I tried this test with gcc 9.2.0:
>
>     $ cat aliasing.c
>     struct s {
>         char c;
>         int i;
>     };
>
>     void dosomething(struct s *s);
>
>     int main(void) {
>         unsigned char cbuf[100] = { 0 };
>         float fbuf[100] = { 0 };
>
>         struct s *s0 = (struct s *)(cbuf + 7);
>         struct s *s1 = (struct s *)(fbuf + 7);
>
>         dosomething(s0);
>         dosomething(s1);
>     }
>
>     $ gcc -O2 -Wall -fstrict-aliasing -Wstrict-aliasing=1 -pedantic-errors aliasing.c
>     aliasing.c: In function 'main':
>     aliasing.c:11:38: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
>        11 |     struct s s1 = *(struct s *)(fbuf + 7);
>           |                                ~~~~~~^~~~
>
> (plus a linker error due to `dosomething` being undefined)
>
> It warns about the float array, not the unsigned char.  If casting a
> char buffer to a pointer-to-struct is undefined without an additional
> attribute or compiler option then that would be good to know.

Let me just correct myself: I am quite sure both casts indeed violate
the effective type rules.  I began that post trying to demonstrate one
thing and ended in a weird place with little understanding of how I got
there!  I think that `-Wstring-aliasing` option is just not very
reliable and I let myself be convinced of some things I know aren't
true.

I really just wanted to demonstrate that gcc will always let a
pointer-to-packed-struct alias a character buffer.  I have always
assumed this is the case because it has always "worked", but I can't
find this guarantee documented anywhere so perhaps I've just gotten
lucky. 

> In any case, I feel like I've said my piece as best I could.
>
> Chris

[toc] | [prev] | [next] | [standalone]


#147949

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-12 10:54 +0100
Message-ID<qqdvg7$n95$1@dont-email.me>
In reply to#147947
On 12/11/2019 08:01, Christopher Collins wrote:
> On 2019-11-11, David Brown <david.brown@hesbynett.no> wrote:
>> On 11/11/2019 18:26, Christopher Collins wrote:
>>> Rather than needing to implement unmarshalling code for every header and
>>> command in a stack, you simply do this:
>>>
>>>      struct foo_header *hdr = (struct foo_header *)buf;
>>>
>>> and you have a header ready to be processed.
>>>
>>
>> Except that you don't - you have to be careful with casting pointer 
>> types, or fall foul of aliasing rules.  If you are doing a lot of this 
>> kind of thing, you might like to add:
>>
>> #pragma GCC optimize("-fno-strict-aliasing")
>>
>> and then the cast is safe (on gcc or clang).
> 
> I'm not sure that's true, but I'll admit that I'm not terribly familiar
> with the C spec.  I tried this test with gcc 9.2.0:
> 
>     $ cat aliasing.c
>     struct s {
>         char c;
>         int i;
>     };
> 
>     void dosomething(struct s *s);
> 
>     int main(void) {
>         unsigned char cbuf[100] = { 0 };
>         float fbuf[100] = { 0 };
> 
>         struct s *s0 = (struct s *)(cbuf + 7);
>         struct s *s1 = (struct s *)(fbuf + 7);
> 
>         dosomething(s0);
>         dosomething(s1);
>     }
> 
>     $ gcc -O2 -Wall -fstrict-aliasing -Wstrict-aliasing=1 -pedantic-errors aliasing.c
>     aliasing.c: In function 'main':
>     aliasing.c:11:38: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
>        11 |     struct s s1 = *(struct s *)(fbuf + 7);
>           |                                ~~~~~~^~~~
> 
> (plus a linker error due to `dosomething` being undefined)
> 
> It warns about the float array, not the unsigned char.  If casting a
> char buffer to a pointer-to-struct is undefined without an additional
> attribute or compiler option then that would be good to know.
> 
> In any case, I feel like I've said my piece as best I could.
> 
> Chris
> 

"-fstrict-aliasing", which is enable with optimisation unless you have
"-fno-strict-aliasing", does not mean that code that messes with pointer
types contrary to 6.5p7 will not work.  It merely means that they might
not work - there are no guarantees.  Whether the code will work or not
will depend on the optimisation opportunities seen and used by the compiler.

The warnings, usually from "-Wstrict-aliasing=3" (the default if
-fstrict-aliasing and -Wall are in effect - "-Wstrict-aliasing=1" is
less accurate), are supposed to be shown if the compiler has taken
advantage of type-based aliasing for optimisation, and generated code
that is different than you would get if C allowed access to data via any
lvalue type.

[toc] | [prev] | [next] | [standalone]


#147952

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-11-12 14:43 +0000
Message-ID<slrnqslh8j.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#147949
On Tue, 2019-11-12, David Brown wrote:
> On 12/11/2019 08:01, Christopher Collins wrote:
>> On 2019-11-11, David Brown <david.brown@hesbynett.no> wrote:
>>> On 11/11/2019 18:26, Christopher Collins wrote:
>>>> Rather than needing to implement unmarshalling code for every header and
>>>> command in a stack, you simply do this:
>>>>
>>>>      struct foo_header *hdr = (struct foo_header *)buf;
>>>>
>>>> and you have a header ready to be processed.
>>>>
>>>
>>> Except that you don't - you have to be careful with casting pointer 
>>> types, or fall foul of aliasing rules.  If you are doing a lot of this 
>>> kind of thing, you might like to add:
>>>
>>> #pragma GCC optimize("-fno-strict-aliasing")
>>>
>>> and then the cast is safe (on gcc or clang).
>> 
>> I'm not sure that's true, but I'll admit that I'm not terribly familiar
>> with the C spec.  I tried this test with gcc 9.2.0:
>> 
>>     $ cat aliasing.c
>>     struct s {
>>         char c;
>>         int i;
>>     };
>> 
>>     void dosomething(struct s *s);
>> 
>>     int main(void) {
>>         unsigned char cbuf[100] = { 0 };
>>         float fbuf[100] = { 0 };
>> 
>>         struct s *s0 = (struct s *)(cbuf + 7);
>>         struct s *s1 = (struct s *)(fbuf + 7);
>> 
>>         dosomething(s0);
>>         dosomething(s1);
>>     }
>> 
>>     $ gcc -O2 -Wall -fstrict-aliasing -Wstrict-aliasing=1 -pedantic-errors aliasing.c
>>     aliasing.c: In function 'main':
>>     aliasing.c:11:38: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
>>        11 |     struct s s1 = *(struct s *)(fbuf + 7);
>>           |                                ~~~~~~^~~~
>> 
>> (plus a linker error due to `dosomething` being undefined)
>> 
>> It warns about the float array, not the unsigned char.  If casting a
>> char buffer to a pointer-to-struct is undefined without an additional
>> attribute or compiler option then that would be good to know.
>> 
>> In any case, I feel like I've said my piece as best I could.
>> 
>> Chris
>> 
>
> "-fstrict-aliasing", which is enable with optimisation unless you have
> "-fno-strict-aliasing", does not mean that code that messes with pointer
> types contrary to 6.5p7 will not work.  It merely means that they might
> not work - there are no guarantees.  Whether the code will work or not
> will depend on the optimisation opportunities seen and used by the compiler.
>
> The warnings, usually from "-Wstrict-aliasing=3" (the default if
> -fstrict-aliasing and -Wall are in effect - "-Wstrict-aliasing=1" is
> less accurate), are supposed to be shown if the compiler has taken
> advantage of type-based aliasing for optimisation, and generated code
> that is different than you would get if C allowed access to data via any
> lvalue type.

Aren't there special language rules so that it's ok to alias when one
of the types is char or unsigned char?  Or maybe I'm confusing this
with something else (I don't do struct mapping myself, unless paid to).

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#147956

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-11-12 10:54 -0500
Message-ID<qqekji$k16$1@dont-email.me>
In reply to#147952
On 11/12/19 9:43 AM, Jorgen Grahn wrote:
...
> Aren't there special language rules so that it's ok to alias when one
> of the types is char or unsigned char?  Or maybe I'm confusing this
> with something else (I don't do struct mapping myself, unless paid to).

Not quite; not all of the anti-aliasing rules are symmetrical. In some
of the rules, the effective type plays a different role than the type of
the lvalue used to access it:

"An object shall have its stored value accessed only by an lvalue
expression that has one of the following types: 88)
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of
the object,
— a type that is the signed or unsigned type corresponding to the
effective type of the object,
— a type that is the signed or unsigned type corresponding to a
qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a
subaggregate or contained union), or
— a character type."
(6.5p7)

Therefore, an object with any effective type can be accessed using an
lvalue of character type, but the reverse is not true. When the
effective type is a character type, there's examples of types that fit
each of the options listed in 6.5p7, but there's also many types that
don't fit any of them. For instant, "short int".

Similarly, you can alias an object which has an effective type that is
an aggregate or union type, using an lvalue of the type of one of it's
members. However, if the effective type of an object is type of one of
it's members, you cannot, in general, access it using an lvalue of that
aggregate or union type.

[toc] | [prev] | [next] | [standalone]


#147970

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-12 19:37 +0100
Message-ID<qqeu4v$l3l$1@dont-email.me>
In reply to#147956
On 12/11/2019 16:54, James Kuyper wrote:
> On 11/12/19 9:43 AM, Jorgen Grahn wrote:
> ...
>> Aren't there special language rules so that it's ok to alias when one
>> of the types is char or unsigned char?  Or maybe I'm confusing this
>> with something else (I don't do struct mapping myself, unless paid to).
> 
> Not quite; not all of the anti-aliasing rules are symmetrical. In some
> of the rules, the effective type plays a different role than the type of
> the lvalue used to access it:
> 
> "An object shall have its stored value accessed only by an lvalue
> expression that has one of the following types: 88)
> — a type compatible with the effective type of the object,
> — a qualified version of a type compatible with the effective type of
> the object,
> — a type that is the signed or unsigned type corresponding to the
> effective type of the object,
> — a type that is the signed or unsigned type corresponding to a
> qualified version of the effective type of the object,
> — an aggregate or union type that includes one of the aforementioned
> types among its members (including, recursively, a member of a
> subaggregate or contained union), or
> — a character type."
> (6.5p7)
> 
> Therefore, an object with any effective type can be accessed using an
> lvalue of character type, but the reverse is not true. When the
> effective type is a character type, there's examples of types that fit
> each of the options listed in 6.5p7, but there's also many types that
> don't fit any of them. For instant, "short int".
> 
> Similarly, you can alias an object which has an effective type that is
> an aggregate or union type, using an lvalue of the type of one of it's
> members. However, if the effective type of an object is type of one of
> it's members, you cannot, in general, access it using an lvalue of that
> aggregate or union type.
> 

The other thing that might play a part here are the rules for changing 
the effective type for "an object having no declared type".  As far as I 
know, that can only actually apply to memory returned by malloc() and 
friends.  However, if the compiler is dealing with a function that 
receives a pointer via a parameter, it usually can't know if it pointed 
to "an object having no declared type" or something with a declared type 
(like a statically allocated or local object).  This means that 
compilers will often assume that it is okay to store data and read data 
via the pointer, because it often /is/ okay to do so.

The point at which compilers are more likely to make use of type-based 
aliasing, and thus give you warnings about problems, would be if the 
function tried to access the memory as two different types at the same 
time.  In this case, it would be storing floats in the "fbuf" array, 
using the array as though it were an array of "struct s", and then 
expected to be able to access the original floats again.

[toc] | [prev] | [next] | [standalone]


#147287

FromRobert Wessel <robertwessel2@yahoo.com>
Date2019-10-27 08:36 -0500
Message-ID<d17bre98fcucvqu9hgb1ivgj39es3iqfvo@4ax.com>
In reply to#147279
On Sun, 27 Oct 2019 03:46:42 -0700 (PDT), already5chosen@yahoo.com
wrote:

>On Saturday, October 26, 2019 at 10:54:34 PM UTC+3, jacobnavia wrote:
>> Le 26/10/2019 à 20:41, Robert Wessel a écrit :
>> > That is not true of all 64-bit implementations, of course.  Consider
>> > MSVC invoked with /Zp1.  Of course it's true of many implementations.
>> 
>> Yes, packing fields would be possible in processors like the x86. It is 
>> not possible in RISC processors where alignment is much stricter.
>
>There are only 2 high-performance RISCs that are still relevant for new development: ARM/ARM64 and POWER. ARM has no alignment requirements on the integer side of the ISA. The same for Power in Big Endian mode. As far as I remember, Power operating in Little Endian mode used to have alignment requirements, but it seems that since Power8 they have "pure little-endian" mode that removes these limitations.


AFAIK, POWER always allows non-aligned "normal*" accesses that don't
cross page boundaries.  The ISA definitions allow the hardware to
perform page-crossing unaligned accesses in some circumstances**, but
it's not required.  Typically the OS will do the usual trap-and-fixup
thing.

If they've strengthened that guarantee recently, I've missed it.


*Restrictions on some types of accesses, of course.

**More or less, the (page table) attributes of both pages need to be
the same.

[toc] | [prev] | [next] | [standalone]


#147290

Fromalready5chosen@yahoo.com
Date2019-10-27 06:49 -0700
Message-ID<ee581b7b-60bd-4420-8934-fb5f6808990a@googlegroups.com>
In reply to#147287
On Sunday, October 27, 2019 at 3:36:16 PM UTC+2, robert...@yahoo.com wrote:
> On Sun, 27 Oct 2019 03:46:42 -0700 (PDT), already5chosen@yahoo.com
> wrote:
> 
> >On Saturday, October 26, 2019 at 10:54:34 PM UTC+3, jacobnavia wrote:
> >> Le 26/10/2019 à 20:41, Robert Wessel a écrit :
> >> > That is not true of all 64-bit implementations, of course.  Consider
> >> > MSVC invoked with /Zp1.  Of course it's true of many implementations.
> >> 
> >> Yes, packing fields would be possible in processors like the x86. It is 
> >> not possible in RISC processors where alignment is much stricter.
> >
> >There are only 2 high-performance RISCs that are still relevant for new development: ARM/ARM64 and POWER. ARM has no alignment requirements on the integer side of the ISA. The same for Power in Big Endian mode. As far as I remember, Power operating in Little Endian mode used to have alignment requirements, but it seems that since Power8 they have "pure little-endian" mode that removes these limitations.
> 
> 
> AFAIK, POWER always allows non-aligned "normal*" accesses that don't
> cross page boundaries.  The ISA definitions allow the hardware to
> perform page-crossing unaligned accesses in some circumstances**, but
> it's not required.  Typically the OS will do the usual trap-and-fixup
> thing.
> 
> If they've strengthened that guarantee recently, I've missed it.
> 

Considering that today new POWER/PPC cores are coming only from IBM and that behavior of old cores is not going to change, POWER ISA guaranties are less important than how they were back when the field was more diverse. Implementations are what matters.

> 
> *Restrictions on some types of accesses, of course.
> 
> **More or less, the (page table) attributes of both pages need to be
> the same.

[toc] | [prev] | [next] | [standalone]


#147286

FromBonita Montero <Bonita.Montero@gmail.com>
Date2019-10-27 14:23 +0100
Message-ID<qp45p0$6ka$1@news.albasani.net>
In reply to#147261
> Yes, packing fields would be possible in processors like the x86. It is 
> not possible in RISC processors where alignment is much stricter. And 
> even in the x86 you get a penalty for misaligned pointer data.

You can have bit-fields with any architecture.

[toc] | [prev] | [next] | [standalone]


Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web