Re: Bitfields problem
Interestingly enough, if I do this instead: typedef struct sTest { int a:12; int b:20; int c:7; int d:15; }STest; int64_t bar2 (STest *a) { int64_t res = a-b; return res; } I get at the expand pass : (insn 6 5 7 3 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg/v/f:DI 73 [ a ]) [0 S4 A32])) -1 (nil)) - Actually get the data (insn 7 6 8 3 struct3.c:27 (set (reg:DI 77) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) -1 (nil)) - Extract the bits we want but this is zero_extracted (insn 8 7 9 3 struct3.c:27 (set (reg:DI 78) (ashift:DI (reg:DI 77) (const_int 43 [0x2b]))) -1 (nil)) (insn 9 8 10 3 struct3.c:27 (set (subreg:DI (reg:SI 76) 0) (ashiftrt:DI (reg:DI 78) (const_int 43 [0x2b]))) -1 (nil)) - These two instructions actually sign extend it (insn 10 9 11 3 struct3.c:27 (set (reg:DI 79) (ashift:DI (reg:SI 76) (const_int 32 [0x20]))) -1 (nil)) (insn 11 10 12 3 struct3.c:27 (set (reg:DI 74) (ashiftrt:DI (reg:DI 79) (const_int 32 [0x20]))) -1 (expr_list:REG_EQUAL (sign_extend:DI (reg:SI 76)) (nil))) - Because it's seen as a SI, these last two sign extend it again... And I get later on in the passes (the instructions are removed by the combine pass): (insn 6 3 7 2 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg:DI 8 r8 [ a ]) [0 S4 A32])) 74 {movsi_internal2} (expr_list:REG_DEAD (reg:DI 8 r8 [ a ]) (nil))) (note 7 6 8 2 NOTE_INSN_DELETED) (note 8 7 9 2 NOTE_INSN_DELETED) (note 9 8 10 2 NOTE_INSN_DELETED) (note 10 9 11 2 NOTE_INSN_DELETED) (note 11 10 16 2 NOTE_INSN_DELETED) (insn 16 11 22 2 struct3.c:30 (set (reg/i:DI 6 r6) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) 63 {extzvdi} (expr_list:REG_DEAD (reg:SI 75) (nil))) So now I have two issues that I can't seem to figure out : - Why can combine remove these 4 instructions ? - Why do I have such a difference between a local variable that is not a pointer, a pointer and a global variable ? I remember having a different behavior if the variable was a global variable or if it was a parameter. It seems that this is the case also for here. However, this is worse, since it transforms my signed extract into a simple zero_extract. Thanks for your help, Jc PS: here is the combine pass debug information: ;; Function bar2 (bar2) starting the processing of deferred insns ending the processing of deferred insns df_analyze called insn_cost 2: 4 insn_cost 6: 4 insn_cost 7: 36 insn_cost 8: 4 insn_cost 9: 4 insn_cost 10: 4 insn_cost 11: 4 insn_cost 16: 4 insn_cost 22: 0 deferring deletion of insn with uid = 2. modifying insn i3 6 r75:SI=[r8:DI] REG_DEAD: r8:DI deferring rescan insn with uid = 6. deferring deletion of insn with uid = 8. modifying insn i3 9 r76:SI#0=r77:DI REG_DEAD: r77:DI deferring rescan insn with uid = 9. deferring deletion of insn with uid = 7. modifying insn i3 9 r76:SI#0=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 9. deferring deletion of insn with uid = 10. modifying insn i311 r74:DI=r76:SI#00xf REG_DEAD: r76:SI deferring rescan insn with uid = 11. deferring deletion of insn with uid = 9. modifying insn i311 r74:DI=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 11. deferring deletion of insn with uid = 11. modifying insn i316 r6:DI=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 16. (note 1 0 4 NOTE_INSN_DELETED) (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) (note 2 4 3 2 NOTE_INSN_DELETED) (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) (insn 6 3 7 2 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg:DI 8 r8 [ a ]) [0 S4 A32])) 74 {movsi_internal2} (expr_list:REG_DEAD (reg:DI 8 r8 [ a ]) (nil))) (note 7 6 8 2 NOTE_INSN_DELETED) (note 8 7 9 2 NOTE_INSN_DELETED) (note 9 8 10 2 NOTE_INSN_DELETED) (note 10 9 11 2 NOTE_INSN_DELETED) (note 11 10 16 2 NOTE_INSN_DELETED) (insn 16 11 22 2 struct3.c:30 (set (reg/i:DI 6 r6) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) 63 {extzvdi} (expr_list:REG_DEAD (reg:SI 75) (nil))) (insn 22 16 0 2 struct3.c:30 (use (reg/i:DI 6 r6)) -1 (nil)) starting the processing of deferred insns deleting insn with uid = 2. deleting insn with uid = 7. deleting insn with uid = 8. deleting insn with uid = 9. deleting insn with uid = 10. deleting insn with uid = 11. rescanning insn with uid = 6. deleting insn with uid = 6. rescanning insn with uid = 16. deleting insn with uid = 16. ending the processing of deferred insns ;; Combiner totals: 16 attempts, 16 substitutions (2 requiring new space), ;; 6 successes. On Fri, Dec 11, 2009 at 11:57 AM, Jean Christophe
Re: Bitfields
reg.field1 = val1, reg.field2 = val2; would then turn into fetch, mask with a combined mask of field1 and field2, or val1, or val2, store. You can also do the RMW yourself: declare the register volatile, but not the fields of it, and copy in/out of the register manually. volatile struct reg x; ... { struct reg mine = x; mine.field1 = true; mine.field2 = 0; mine.field3++; x = mine; } Is it a completely brain-dead idea? If I understood it correctly, it would not be standard compliant. Paolo
Re: Bitfields
Paolo Bonzini wrote: Is it a completely brain-dead idea? If I understood it correctly, it would not be standard compliant. But it's an extension, so I don't see that is an issue of itself. Paolo
Re: Bitfields
On Sun, 20 Sep 2009, Zolt??n K??csi wrote: I wonder if there would be at least a theoretical support by the developers to a proposal for volatile bitfields: It has been proposed (and not rejected, but not yet implemented) that volatile bit-fields should follow the ARM EABI specification (on all targets); that certainly seems better than inventing something new unless you have a very good reason to prefer the something new on some targets. -- Joseph S. Myers jos...@codesourcery.com
Re: Bitfields
On Sun, 20 Sep 2009, Joseph S. Myers wrote: On Sun, 20 Sep 2009, Zolt??n K??csi wrote: I wonder if there would be at least a theoretical support by the developers to a proposal for volatile bitfields: It has been proposed (and not rejected, but not yet implemented) that volatile bit-fields should follow the ARM EABI specification (on all targets); that certainly seems better than inventing something new unless you have a very good reason to prefer the something new on some targets. Yes, that discussion was that made me thinking and suggesting this *before* the ARM EABI gets implemented. I don't suggest to implement something instead of the ARM EABI, I suggest to implement something on top of it. The suggested behaviour is also architecture-neutral. It is nothing more than if the user expressly asks the compiler to break the standard in a particular way, then the compiler does so. The breaking of the standard is at one single point. The ARM EABI spec clearly states that bitfield operations are never to be combined, not even in the case where consecutive bitfield assignments refer to bitfields located in the same machine word. My suggestion was that if a new command line switch is present, then in the special case of consecutive bitfield assignments being made to fields within the same word and the assignments being separated by the comma operator, then the compiler combines those assignments. The rationale of such behaviour is writing low-level code dealing with HW registers. To have a practical example, let's have a SoC chip with multi-function pins. Let's assume that we have a register that has 2 bits for each actual pin and the value of the 2 bits selects the actual function for the pin; a 32 bit register can thus control 16 pins. Now if you want to, say, assign 4 pins to the SPI interface, without bitfields you would (and indeed do) write something along these lines: temp = *pin_control_reg; temp = ~(PIN_03_MASK | PIN_04_MASK | PIN_05_MASK | PIN_06_MASK); temp |= PIN_O3_MISO | PIN_04_MOSI | PIN_05_SCLK | PIN_06_SSEL; *pin_ctrl_reg = temp; You can't really use bitfields to achieve the above, because if you write pin_control_reg-pin_03 = MISO; pin_control_reg-pin_04 = MOSI; and so on, pin_xx being 2-bit wide bitfields, then according to the ARM EABI spec each statement would be translated to a temp = *pin_contorl_reg; temp =...; temp |=...; *pin_control_reg=temp; sequence. What I suggest is that if you write pin_control_reg-pin_03 = MISO, // Note the comma pin_control_reg-pin_04 = MOSI, pin_control_reg-pin_05 = SCLK, pin_control_reg-pin_06 = SSEL; and compile it with a -fcomma-combines-bitfields switch, then you get the equivalent of the first code fragment where you manually combined the masks and the settings and only a single load and a single store was used. If the switch is not given or the consecutive assignments are not separated by commas or the bitfields do not belong to the same word, then the behaviour falls back to the default ARM EABI spec. The advantage of the suggested behaviour is that it would allow the use of the more elegant and expressive bitfields in place of the many hundreds of #define REGNAME_FIELDNAME_MASK and #define REGNAME_FIELDNAME_SHIFT macros that you can currently find in code that deals with HW. The suggestion does not introduce any new functionality or performance advantage, it just provides a way of writing (in my opinion) more readable and more maintainable code than what we have now with all the #defines. The fact that structure members live in their own namespace as opposed to the global #define namespace is an added benefit, of course. The suggested extension does not break backward compatibility, because the #define stuff would not be affected and the ARM EABI is not yet implemented anyway; it would not break the expected behaviour because it becomes active only when an explicite command line switch is given and has no side-effects outside the single expression where the subexpressions are separated by commas. The change, I believe, would benefit gcc users who deal with HW a lot, i.e. low level embedded system and device driver designers. Outside of that circle the suggested behavior would have only a little performance benefit. Zoltan
Re: bitfields: types vs modes?
At the risk of being naive: implement it. I'm not quite sure what you're looking for here? Ok, time to ask for a hint. I started at get_best_mode(), adding a TREE argument for the type, and worked my way out, adding arguments to functions as needed to propogate the type information. It's getting out of hand. Is there some easier way to track the type that an rtx came from? Perhaps we could call get_best_mode() earlier in the whole process, and put that mode in the rtx instead of BLKmode ?
Re: bitfields: types vs modes?
I think the ARM specification is pretty sensible, and would make a good cross-platform approach. Could you distill it for us? The relevant bits are from AAPCS \S 7.1.7.5, and quoted below. I finally got the last of the feedback I needed from our customers, and they agree that the AAPCS functionality is suitable for their ports as well. What's the next step?
Re: bitfields: types vs modes?
DJ Delorie wrote: I think the ARM specification is pretty sensible, and would make a good cross-platform approach. I finally got the last of the feedback I needed from our customers, and they agree that the AAPCS functionality is suitable for their ports as well. Great! What's the next step? At the risk of being naive: implement it. I'm not quite sure what you're looking for here? I'd assume that we should try to do some of this at the tree-rtl conversion point, in a platform-independent manner, but I'm not an expert on those bits. Thanks, -- Mark Mitchell CodeSourcery m...@codesourcery.com (650) 331-3385 x713
Re: bitfields: types vs modes?
At the risk of being naive: implement it. I'm not quite sure what you're looking for here? I'd rather have some confidence that the way I choose to implement it would be acceptable to those who would be reviewing it ;-) I'll give it a shot at the same point in the code where we call the target now.
Re: bitfields: types vs modes?
DJ Delorie wrote: I think the ARM specification is pretty sensible, and would make a good cross-platform approach. Could you distill it for us? The relevant bits are from AAPCS \S 7.1.7.5, and quoted below. The term container here means the declared type of the bit-field. (There's a corner-case for C++ bit-fields that are bigger than their declared type, but don't worry about that.) So int i:6 has a 32-bit container, whereas char c:6 has an 8-bit container. (In the ARM ABI, a bit-field never crosses a container boundary; struct { char c1:6; char c2:3} puts c2 completely into the second byte, not straddling the first two bytes. But, if those were int bit-fields, then the second bit-field would straddle the two bytes. Packed structures are outside the scope of the ABI.) When a volatile bit-field is read, its container must be read exactly once using the access width appropriate to the type of the container. When a volatile bit-field is written, its container must be read exactly once and written exactly once using the access width appropriate to the type of the container. The two accesses are not atomic. Multiple accesses to the same volatile bit-field, or to additional volatile bit-fields within the same container may not be merged. For example, an increment of a volatile bit-field must always be implemented as two reads and a write. Note the volatile access rules apply even when the width and alignment of the bit-field imply that the access could be achieved more efficiently using a narrower type. For a write operation the read must always occur even if the entire contents of the container will be replaced. If the containers of two volatile bit-fields overlap then access to one bit-field will cause an access to the other. For example, in struct S {volatile int a:8; volatile char b:2}; an access to a will also cause an access to b, but not vice-versa. If the container of a non-volatile bit-field overlaps a volatile bit-field then it is undefined whether access to the non-volatile field will cause the volatile field to be accessed. -- Mark Mitchell CodeSourcery m...@codesourcery.com (650) 331-3385 x713
Re: bitfields: types vs modes?
We seem to have dropped this discussion. I now have *two* customers asking for this functionality. Can we pick it up again? We need to decide: 1. If the functionality will be allowed in gcc at all 2. What info the target needs to be provided to make the choices it wants 3. What, if any, common code can be shared between the CPUs
Re: bitfields: types vs modes?
Ian Lance Taylor wrote: 1. If the functionality will be allowed in gcc at all 2. What info the target needs to be provided to make the choices it wants 3. What, if any, common code can be shared between the CPUs Since the ARM ABI apparently specifies something about volatile bitfields, I think we ought to implement that. Yes, we should. I am aware of real user demand for this feature as well. It's a competitive disadvantage for GCC not to have this feature. I continue to think that a sane programmer would use a different mechanism. C/C++ provides mechanisms for working with memory mapped hardware. Bitfields are not one of those mechanisms. I think the ARM specification is pretty sensible, and would make a good cross-platform approach. Using bit-fields may not be portable at present, but it would sure be nice if it was; it maps directly onto how people think about memory-mapped peripherals. -- Mark Mitchell CodeSourcery m...@codesourcery.com (650) 331-3385 x713
Re: bitfields: types vs modes?
I think the ARM specification is pretty sensible, and would make a good cross-platform approach. Could you distill it for us? If it's acceptable to my two customers, it would be a good starting point to define an API for the targets.
Re: bitfields: types vs modes?
Ian Lance Taylor wrote: So... can I/we move forward on this? Or will such a change be rejected? It's hard for me to get excited about something like this. It's straightforward a programmer to write code that is clearly correct in this sort of situation: just don't use a bitfield. In part, because of the ARM ABI issue, I think we ought to accept patches that fix this problem. It's true that GCC doesn't in general document these semantics, but users of some ABIs have expectations about how volatile bitfields will work. DJ, I'd suggest you look at: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042c/IHI0042C_aapcs.pdf and, in particular, \S 7.1.7.5, entitled Volatile bit-fields. A first question is if these are the semantics that you're looking for in your project. If so, then we could collaborate with you on implementing them. If not, there may be still be some common parts. -- Mark Mitchell CodeSourcery m...@codesourcery.com (650) 331-3385 x713
Re: bitfields: types vs modes?
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042c/IHI0042C_aapcs.pdf and, in particular, \S 7.1.7.5, entitled Volatile bit-fields. A first question is if these are the semantics that you're looking for in your project. If so, then we could collaborate with you on implementing them. If not, there may be still be some common parts. Yes, that's pretty much what they asked for. However, it is still somewhat ambiguous - for example, if you have an 8-bit int field, which 4 bytes are read to get that field? Should we take into consideration adjacent field types, or the type's natural alignment? What if the field spans natural alignment boundaries? What if the larger-than-field access exceeds the memory region and causes a fault? For example, in this case, when we access x.b does it also read a, or c? Will reading x.d cause a segment fault? volatile struct { char a:8; int b:24; char c:8; int d:8; } x; We need to figure out how much information we should pass to the target to let it make these decisions, if it needs to. A common function to do by-type access could be called from your target and mine.
Re: bitfields: types vs modes?
DJ Delorie wrote: Yes, that's pretty much what they asked for. However, it is still somewhat ambiguous - for example, if you have an 8-bit int field, which 4 bytes are read to get that field? I haven't gone back just now to try to find the right words in the ABI, so I don't know for sure that they're there, but the intent is the types' natural alignment. All int bit-fields in that ABI are located within a 32-bit aligned range of memory; the intent is that you read/write that entire 4-byte range. In other words, take the byte address of the start of the bit-field, mask off the two low-order bits, that's the 4-byte address to read. On an ARM, you can never cross a protection boundary in that way; you're never going to get a SEGV from the bytes you read in that way if you wouldn't have gotten one from the byte containing the start of the bit-field. Protection is done at the page (or cache-line, I forget) boundary; in either case, the granularity of protection is greater than the granularity of any basic type. And, if it's not, that's your problem; the ABI semantics of a volatile bit-field of type T are that you get sizeof(T) bytes, and if it blows up (which I don't think it can), it's not the compiler's fault. If you have an ABI where an int bit-field can cross a sizeof(int)-byte boundary, that's a harder case. That can happen on ARM with GCC's packed-structure extension, but that's outside the ARM ABI, and therefore the behavior is not specified. We need to figure out how much information we should pass to the target to let it make these decisions, if it needs to. A common function to do by-type access could be called from your target and mine. I'd like to know how many of the assumptions above are valid on your target. I would imagine that many of them are. In which case, the existing hook is good enough; we just need to implement middle-end behavior depending on the hook. -- Mark Mitchell CodeSourcery m...@codesourcery.com (650) 331-3385 x713
Re: bitfields: types vs modes?
So... can I/we move forward on this? Or will such a change be rejected? BTW, Since sending this I discovered that gcc treats these differently wrt TARGET_NARROW_VOLATILE_BITFIELD: volatile struct { unsigned int a:8; unsigned int b:24; } t1; volatile struct { unsigned int a:7; unsigned int b:25; } t2; t1.a will be accessed as a byte regardless of the target's preferences, whereas t2.c follows the target preferences. One of our customers has a chip with memory-mapped peripheral registers that need to be accessed in a specific mode. The registers represent bitfields within the hardware, so a volatile struct is an obvious choice to represent them in C. However, gcc has a very simplistic heuristic for deciding what mode to use to access bitfields in structures - it uses either the biggest or smallest mode practical. This offers the programmer no way to tell gcc what mode the accesses need to be in, aside from manually reading/writing memory with integer types and casting. Options? My thought, after some internal discussion, is that (if the target chooses) we allow gcc to honor the type of a volatile bitfield as the mode as long as it can do so without otherwise violating the structure's layout. Some new hook will be needed for the backend, and perhaps a -W option for when the type cannot be honored. I.e. if the programmer is careful enough to properly lay out the struct, the programmer should get what the programmer asks for. Comments? Alternatives?
Re: bitfields: types vs modes?
DJ Delorie d...@redhat.com writes: So... can I/we move forward on this? Or will such a change be rejected? BTW, Since sending this I discovered that gcc treats these differently wrt TARGET_NARROW_VOLATILE_BITFIELD: volatile struct { unsigned int a:8; unsigned int b:24; } t1; volatile struct { unsigned int a:7; unsigned int b:25; } t2; t1.a will be accessed as a byte regardless of the target's preferences, whereas t2.c follows the target preferences. One of our customers has a chip with memory-mapped peripheral registers that need to be accessed in a specific mode. The registers represent bitfields within the hardware, so a volatile struct is an obvious choice to represent them in C. However, gcc has a very simplistic heuristic for deciding what mode to use to access bitfields in structures - it uses either the biggest or smallest mode practical. This offers the programmer no way to tell gcc what mode the accesses need to be in, aside from manually reading/writing memory with integer types and casting. Options? My thought, after some internal discussion, is that (if the target chooses) we allow gcc to honor the type of a volatile bitfield as the mode as long as it can do so without otherwise violating the structure's layout. Some new hook will be needed for the backend, and perhaps a -W option for when the type cannot be honored. I.e. if the programmer is careful enough to properly lay out the struct, the programmer should get what the programmer asks for. Comments? Alternatives? It's hard for me to get excited about something like this. It's straightforward a programmer to write code that is clearly correct in this sort of situation: just don't use a bitfield. gcc doesn't even document the order of bits in a bitfield, so it's generally difficult to reliably use bitfields to access memory mapped registers. If this were my customer, I would tell them to write inline functions which access the data as integers of the appropriate size and do the required shifting and masking. That code only has to be written once, it will be just as efficient as the code generated by using a volatile bitfield struct, and it will be clearly correct with any reasonable compiler. A volatile bitfield is a dubious construct all by itself. The volatile qualifier is supposed to direct the compiler to act exactly like the virtual machine. But what does the virtual machine do on an assignment to a volatile bitfield? Many real machines must read the value, change some bits, and then write the value back. Is that following the virtual machine or not? Is the volatile qualifier misleading in such a case? In any case, while I recommend against it, I won't stop you if you really want to follow your proposal. The most important thing for this approach would be the documentation, so write that first. Your brief description above is insufficient; I'm not sure what you mean by without otherwise violating the structure's layout, and I don't know why you might need a -W option. Then, of course, you will need a fairly complete set of test cases. I want to say that I think that this comment: I.e. if the programmer is careful enough to properly lay out the struct, the programmer should get what the programmer asks for. is misleading. When I give a type to a bitfield, I don't think I am asking for the bitfield to be accessed in that type. It's not a case of the programmer getting what he or she asks for; it's a case of the programmer wants to define a specific set of semantics to bitfields, a language construct which can provide a range of different semantics. Ian
Re: bitfields: types vs modes?
On Tuesday 10 March 2009, DJ Delorie wrote: One of our customers has a chip with memory-mapped peripheral registers that need to be accessed in a specific mode. The registers represent bitfields within the hardware, so a volatile struct is an obvious choice to represent them in C. Comments? Alternatives? PR23623 (I suspect the status on that bug is incorrect, it's nt actually fixed). The ARM EABI defines semantics for volatile bitfields, and gcc gets this wrong. Paul
Re: bitfields: types vs modes?
On Wed, 2009-03-11 at 01:05 -0400, DJ Delorie wrote: Can you provide example code? I'm confused enough to believe that you *should* get this effect with PCC_BITFIELD_TYPE_MATTERS (modulo current bugs). Imagine a device with four 8-bit registers followed by a 32-bit register with an 8-bit field: byte status (read-only, clears after reading) byte control (read/write) byte tx buf (write only) byte rx buf (read only) long uart configuration divisor:8 bits:3 stop:1 start:1 reserved:3 clock source:8 pin_selection:8 so, you'd do this: typedef struct { char status:8; char control:8; char tx:8; char rx:8; long divisor:8; long bits:3; long stop:1; long start:1; long reserved:3; long clock_source:8; long pin_selection:8; } UartDev; extern volatile UartDev uart1; If you use SImode to access any of the first four registers, you may end up clearing a status bit you haven't read yet. If you use QImode to write the divisor, you may end up clearing the other bits if gcc doesn't drive the right values onto the bus. With our current code, the mode for access for the above would either always be QI or always be SI; there's no way to have QI for the first four and SI for the rest. The culprit is get_best_mode(), which doesn't know the C type of the field. PCC_BITFIELD_TYPE_MATTERS seems to only control layout, not access. Even if it did solve the type-v-mode problem, turning it on would break ABI compatibility. I don't know how the Ada front-end achieve this and wether it's portable but the following seem to work: procedure Aa is type U8 is mod 2**8; for U8'Size use 8; pragma Atomic (U8); type U8B is mod 2**8; type U3B is mod 2**3; type U1B is mod 2; type R1 is record B1 : U8B; B2 : U3B; B3 : U1B; B4 : U1B; B5 : U3B; B6, B7 : U8B; end record; pragma Pack (R1); pragma Atomic (R1); type R is record B1, B2, B3, B4 : U8; B5 : R1; end record; pragma Pack (R); pragma Volatile (R); X : R; X1 : R1; begin X.B1 := 0; X.B2 := 0; X.B3 := 0; X.B4 := 0; X1 := X.B5; end AA; gcc -S -O2 aa.adb _ada_aa: .LFB1: movb$0, -12(%rsp) movb$0, -11(%rsp) movb$0, -10(%rsp) movb$0, -9(%rsp) movl$0, -24(%rsp) ret
Re: bitfields: types vs modes?
On Wed, 11 Mar 2009, Paul Brook wrote: PR23623 (I suspect the status on that bug is incorrect, it's nt actually fixed). The ARM EABI defines semantics for volatile bitfields, and gcc gets this wrong. If the ARM EABI really documents the semantics for that, implement-c.texi:Qualifiers does need to defer to the ABI just as the other items there, rather than using weasel words to the effect of flying demons up your nose, ha ha. After fixing the mentioned bug that is; *with* the bug the current wording fits. ;) (Yeah yeah, I know: patches welcome.) brgds, H-P
Re: bitfields: types vs modes?
On Tue, 10 Mar 2009, DJ Delorie wrote: One of our customers has a chip with memory-mapped peripheral registers that need to be accessed in a specific mode. The registers represent bitfields within the hardware, so a volatile struct is an obvious choice to represent them in C. Thank you for those words. ;) (There was a minor argument on IRC some time ago on a related subject.) However, gcc has a very simplistic heuristic for deciding what mode to use to access bitfields in structures - it uses either the biggest or smallest mode practical. This offers the programmer no way to tell gcc what mode the accesses need to be in, aside from manually reading/writing memory with integer types and casting. And not even *then* are you guaranteed the intended semantics as per the documentation (though at least each target should be able to promise that, IMNSHO). IMHO GCC should have the means to do what you suggest for *all* targets; memory-mapped I/O that needs to be accessed in a specific mode is a general-enough situation. Options? My thought, after some internal discussion, is that (if the target chooses) we allow gcc to honor the type of a volatile bitfield as the mode as long as it can do so without otherwise violating the structure's layout. Some new hook will be needed for the backend, and perhaps a -W option for when the type cannot be honored. I.e. if the programmer is careful enough to properly lay out the struct, the programmer should get what the programmer asks for. Can you provide example code? I'm confused enough to believe that you *should* get this effect with PCC_BITFIELD_TYPE_MATTERS (modulo current bugs). Comments? The concept is certainly agreeable. I'd recommend -fno-tree-sra when you inspect current behavior; there be bugs there. Sorry, no PR yet. brgds, H-P
Re: bitfields: types vs modes?
Can you provide example code? I'm confused enough to believe that you *should* get this effect with PCC_BITFIELD_TYPE_MATTERS (modulo current bugs). Imagine a device with four 8-bit registers followed by a 32-bit register with an 8-bit field: bytestatus (read-only, clears after reading) bytecontrol (read/write) bytetx buf (write only) byterx buf (read only) longuart configuration divisor:8 bits:3 stop:1 start:1 reserved:3 clock source:8 pin_selection:8 so, you'd do this: typedef struct { char status:8; char control:8; char tx:8; char rx:8; long divisor:8; long bits:3; long stop:1; long start:1; long reserved:3; long clock_source:8; long pin_selection:8; } UartDev; extern volatile UartDev uart1; If you use SImode to access any of the first four registers, you may end up clearing a status bit you haven't read yet. If you use QImode to write the divisor, you may end up clearing the other bits if gcc doesn't drive the right values onto the bus. With our current code, the mode for access for the above would either always be QI or always be SI; there's no way to have QI for the first four and SI for the rest. The culprit is get_best_mode(), which doesn't know the C type of the field. PCC_BITFIELD_TYPE_MATTERS seems to only control layout, not access. Even if it did solve the type-v-mode problem, turning it on would break ABI compatibility.