From: Philipp K. K. <pk...@sp...> - 2010-01-21 13:59:40
|
I'd like to hear the opinions of other sdcc developers on this topic. >From the discussion in the "Deprecate the __bit keyword?" thread it seems the situation is the following: - Currently _Bool is defined to be the same as __bit in sdcc. - __bit is intended to be a way to allow sdcc users to use an individual bit to store data. It really is only a bit in memory, and thus is smaller than char. It has no address, and further restrictions apply. This seems to be how __bit is implemented on the mcs51. - _Bool should be the full C data type, adressable, etc. This is how I intended to implement __bit on the Z80. Part of it is implemented, you can e.g. take the address of a __bit on the Z80. Thus I would suggest the following: - Introduce _Bool as a keyword, remove the #define _Bool __bit from stdbool.h. - Implement full support for _Bool throughout sdcc and in the backends. This should fix numerous bool-related bugs in the tracker and make sdcc more conforming to the C99 standard. Please tell me what you think about this plan. In case you agree I would try to implement it for Z80 over the weekend (and remove __bit support from the Z80 port since it does not provide any advantage over _Bool there). I would report on how it went and the other ports could follow whenever their maintainers find some time to do it. I expect the amount of work for supporting _Bool in the backends to be minimal: Handling of casts to _Bool (like in Z80's current genCast for __bit) should be sufficient for a conforming implementation. Depending on the hardware further changes could improve code quality (on the Z80 conditional jumps depending on the values of __bit are currently more efficient than testing for the non-zeroness of e.g. unsigned chars). Philipp |
From: Sébastien L. <sq...@gm...> - 2010-01-21 14:33:46
|
Personally, I totally agree with you. For me, __bit should be a platform specific feature for mcus that provide individual bit storage such as the mcs51, and _Bool should be a standard C type supporting all std operations. Regards Sebastien |
From: Borut R. <bor...@si...> - 2010-01-21 16:11:30
|
I agree too. __bit could be also implemented on pic targets, since they have direct bit manipulaution instructions. I don't know about hc08. _Bool should probably be implemented as byte, since there should be a possibility to take the address of _Bool variable and make it a structure member, which is not applicable with __bit type. Borut Sébastien Lorquet wrote: > Personally, I totally agree with you. > For me, __bit should be a platform specific feature for mcus that > provide individual bit storage such as the mcs51, and _Bool should be > a standard C type supporting all std operations. > > Regards > Sebastien |
From: Jan W. <we...@ef...> - 2010-01-21 16:37:12
|
>_Bool should probably be implemented as byte, since there should be a >possibility to take the address of _Bool variable and make it a >structure member, which is not applicable with __bit type. I disagree. Programs using extensively _Bool in the hope of a standard-compliant yet implementation efficient type - relying on _Bool = __bit until now - would be severely penalised, with not simple workaround (once _Bool will be a builtin keyword, with no way to overrule it by the user). While the current implementation of __bit might indeed prevent implementations of _Bool with features requred by standard, implementing _Bool as a byte is a crude cludge worth compilers converted from "general purpose" ones, but not a dedicated 8-bit microcontroller compiler that SDCC is. ;-) I don't think it's reasonable to push this problem too hard for v3.0... JW |
From: Philipp K. K. <pk...@sp...> - 2010-01-21 16:59:12
|
Jan Waclawek schrieb: > > Programs using extensively _Bool in the hope of a standard-compliant > yet implementation efficient type - relying on _Bool = __bit until > now - would be severely penalised, with not simple workaround (once > _Bool will be a builtin keyword, with no way to overrule it by the > user). A #define will overrule anything. One could leave the #define _Bool __bit in stddef.h for some ports in sdcc99 mode if so desired. > > While the current implementation of __bit might indeed prevent > implementations of _Bool with features requred by standard, > implementing _Bool as a byte is a crude cludge worth compilers > converted from "general purpose" ones, but not a dedicated 8-bit > microcontroller compiler that SDCC is. ;-) What's the alternative? The standard mandates sizeof(char) == 1. sizeof(_Bool) can't be zero, so it needs at least a byte. > > I don't think it's reasonable to push this problem too hard for > v3.0... I want to have an implementation of _Bool on the Z80 that is or can be made into a standard-compliant complete one. I would prefer to do have it for 3.0. In 2.9 the Z80 had no _Bool at all. It currently has a _Bool via __bit implementation, with __bit taking up a complete byte. Of course the optimal implementation would be one where for __bit-supporting ports sdcc replaces _Bool by __bit where it doesn't change the semantics, so one would get e.g. the reduced memory usage automatically where possible, and a full byte would used where necessary, e.g. when the _Bool's address is used. However that looks like 1) a lot of work and 2) relies on having a standard-conforming _Bool implementation first. Philipp |
From: Jan W. <we...@ef...> - 2010-01-21 17:19:16
|
>> >> Programs using extensively _Bool in the hope of a standard-compliant >> yet implementation efficient type - relying on _Bool = __bit until >> now - would be severely penalised, with not simple workaround (once >> _Bool will be a builtin keyword, with no way to overrule it by the >> user). > >A #define will overrule anything. One could leave the #define _Bool >__bit in stddef.h for some ports in sdcc99 mode if so desired. True. I take this one back. There is a workaround; still, I don't agree _Bool is required to be a byte by the standard. >> >> While the current implementation of __bit might indeed prevent >> implementations of _Bool with features requred by standard, >> implementing _Bool as a byte is a crude cludge worth compilers >> converted from "general purpose" ones, but not a dedicated 8-bit >> microcontroller compiler that SDCC is. ;-) > >What's the alternative? The standard mandates sizeof(char) == 1. >sizeof(_Bool) can't be zero, so it needs at least a byte. While sizeof(_Bool) can return one, there is no need for it to occupy a WHOLE byte. I see no strict implication in this. I believe this is a grey area not addressed properly (read: ignored) by the current standard. Note, that even 8-bit char was intended originally only to hold characters - nobody assumed there will be arithmetics performed on anything below int (and mind the original K&R v1 int definition); note the resulting turmoil caused by different approach for char default signedness and arithmetics, and note that it took several iterations of the standard to get it to the current state (which is still rather complex and full of greys). Again, SDCC being the forerunner in the 8-bit mcu/mpu area, I believe the principal developers of SDCC are licenced to be a bit creative beyond conservative. We can perhaps break this down to individual items - &, sizeof, structs, arrays, local and external, etc. - and discuss separately for each of them. >> >> I don't think it's reasonable to push this problem too hard for >> v3.0... > >I want to have an implementation of _Bool on the Z80 that is or can be >made into a standard-compliant complete one. I would prefer to do have >it for 3.0. >In 2.9 the Z80 had no _Bool at all. It currently has a _Bool via __bit >implementation, with __bit taking up a complete byte. > >Of course the optimal implementation would be one where for >__bit-supporting ports sdcc replaces _Bool by __bit where it doesn't >change the semantics, so one would get e.g. the reduced memory usage >automatically where possible, and a full byte would used where >necessary, e.g. when the _Bool's address is used. However that looks >like 1) a lot of work and 2) relies on having a standard-conforming >_Bool implementation first. This appears to me as a major job which might need feedback from practical usage; but yes, I am nobody to tell this. But I repeat, I see no requirement from the standard for _Bool to use a whole byte. Sure it is a quick way to implement it; but also inefficient beyond real world usability for most of the 8-bitters, so what's the point of doing so? JW |
From: Philipp K. K. <pk...@sp...> - 2010-01-21 17:24:22
|
Jan Waclawek schrieb: >>> Programs using extensively _Bool in the hope of a >>> standard-compliant yet implementation efficient type - relying on >>> _Bool = __bit until now - would be severely penalised, with not >>> simple workaround (once _Bool will be a builtin keyword, with no >>> way to overrule it by the user). >> A #define will overrule anything. One could leave the #define _Bool >> __bit in stddef.h for some ports in sdcc99 mode if so desired. > > > True. I take this one back. There is a workaround; still, I don't > agree _Bool is required to be a byte by the standard. > > > >>> While the current implementation of __bit might indeed prevent >>> implementations of _Bool with features requred by standard, >>> implementing _Bool as a byte is a crude cludge worth compilers >>> converted from "general purpose" ones, but not a dedicated 8-bit >>> microcontroller compiler that SDCC is. ;-) >> What's the alternative? The standard mandates sizeof(char) == 1. >> sizeof(_Bool) can't be zero, so it needs at least a byte. > > While sizeof(_Bool) can return one, there is no need for it to occupy > a WHOLE byte. I see no strict implication in this. I believe this is > a grey area not addressed properly (read: ignored) by the current > standard. > > Again, SDCC being the forerunner in the 8-bit mcu/mpu area, I believe > the principal developers of SDCC are licenced to be a bit creative > beyond conservative. > > We can perhaps break this down to individual items - &, sizeof, > structs, arrays, local and external, etc. - and discuss separately > for each of them. OK, so assume we have to _Bools x and y in the same byte. That would mean &x == &y, thus *(&x) == *(&y), thus x == y. Philipp |
From: Jan W. <we...@ef...> - 2010-01-21 19:46:59
|
> OK, so assume we have to _Bools x and y in the same byte. That would > mean &x == &y, No. Why would that be? The standard has this to say on the & operator: "The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’." Thus, &x is of type "pointer to _Bool", nothing more, nothing less, it does not need to map to any physical address of any kind. It is sufficient to ensure that *(&x) returns value of x. If you are concerned about using this address to reference a byte (uint8_t), this is said in 6.3.2.3: "A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned57) for the pointed-to type, the behavior is undefined." Q.E.D. :-) Jan |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 11:50:32
|
Jan Waclawek wrote: >> OK, so assume we have to _Bools x and y in the same byte. That >> would mean &x == &y, > > No. Why would that be? > > The standard has this to say on the & operator: "The unary & operator > yields the address of its operand. If the operand has type ‘‘type’’, > the result has type ‘‘pointer to type’’." > > Thus, &x is of type "pointer to _Bool", nothing more, nothing less, > it does not need to map to any physical address of any kind. It is > sufficient to ensure that *(&x) returns value of x. If you are > concerned about using this address to reference a byte (uint8_t), > this is said in 6.3.2.3: > > "A pointer to an object or incomplete type may be converted to a > pointer to a different object or incomplete type. If the resulting > pointer is not correctly aligned57) for the pointed-to type, the > behavior is undefined." OK, that would correspond to the BSEG segment for the linker, as now used on mcs51. But how to map these into the generic address space? We need to be able to cast *bool to *void: 743 A pointer to void may be converted to or from a pointer to any incomplete or object type. 744 A pointer to any incomplete or object type may be converted to a pointer to void and back again; 745 the result shall compare equal to the original pointer. On the Z80 I have 16 bit pointers. I use all 16 bits to point to the bytes in address space. I do not want to waste a lot of RAM space for 24-bit pointers just to save a bit or two for _Bool users. And that's ignoring the probably significant code size increases. Maybe there's an efficient way to do it on the mcs51, with it's bit address space. I don't see one on the Z80. Philipp |
From: Borut R. <bor...@si...> - 2010-01-22 06:49:53
|
I have to explain my statement: I was thinking and writing what is possible to do for sdcc 3.0 release, so "not applicable" should be read as "not feasible for 3.0 release". Jan is absolutely right: bit addressing is possible and many compilers are already using it. Usually it is implemented as (<byte address> * 8 + <bit position in byte>). Actually also the mcs51 sdcc target is using it internally. Using the __bit type in the structure or union could be implemented using bit fields: struct { int a; __bit b; __bit c; char b; } s; can be internally represented as: struct { int a; int b :1; int c :1; char b; } s; But I doubt that we can "enhance" the __bit handling that it can be used as _Boolean, so I propose to implement _Boolean as char for sdcc 3.0. If somebody is willing to start working on __bit handling enhancements before 3.0 release, we can create a svn branch. Borut Borut Razem wrote: > I agree too. > __bit could be also implemented on pic targets, since they have direct > bit manipulaution instructions. I don't know about hc08. > > _Bool should probably be implemented as byte, since there should be a > possibility to take the address of _Bool variable and make it a > structure member, which is not applicable with __bit type. > > Borut > > > > Sébastien Lorquet wrote: > >> Personally, I totally agree with you. >> For me, __bit should be a platform specific feature for mcus that >> provide individual bit storage such as the mcs51, and _Bool should be >> a standard C type supporting all std operations. >> >> Regards >> Sebastien >> |
From: Jan W. <we...@ef...> - 2010-01-22 09:55:50
|
Borut, First, the organisational side of the problem. >But I doubt that we can "enhance" the __bit handling that it can be used >as _Boolean, so I propose to implement _Boolean as char for sdcc 3.0. I suppose, you mean _Bool (the standard boolean type) to occupy a whole byte, being addressed/(de)referenced in the same way as uint8_t; but with properties (conversion/assignment, arithmetics (see (*)) . I also suppose a regression suite will be created simultaneously. This does not sound as a trivial undertaking, either; but as a non-developer, I might be completely wrong. What I see as a major drawback in this approach is, that this gives the impression to the users that the implementation of _Bool to occupy a byte is the final solution. They might then be tempted to (ab)use the (fundamentally incorrect) assumption that pointer of _Bool can be freely converted to any other pointer type; and codebase created with this assumption might later, when moving to true bits, fail. So, here is my proposal as a compromise: let's NOT fix _Bool as a keywork implemented directly in SDCC. Let's implement the byte-bool with a yet another SDCC-specific keyword - say, "__bytebool", or any other; let's properly document both this and __bit, listing both the advantages and disadvantages and the current state of things; and then let the user decide, which one she wants to use as _Bool, using a proper #define. This is for all practical purposes sufficiently close to the standard, and it allows for a transition time for both solutions to mature and to gain enough experience with either of them. --- Now, two technicalities, both illustrated by a snippet of code from Derek Jones's book (page 489, "verse" 474, chapter 6.2.5): 1. (*) - conforming arithmetics of _Bool is not trivial, regardless of if it is implemented as a bit or a byte: extern _Bool E; void f(void) { if (((E ? 1 : 0) != (!(!E))) || ((E += 2) != 1) || ((--E, --E, E) != E)) printf("This is not a conforming implementation\n"); } 2. _Bool in struct can *not* be directly replaced for bitfield of size 1: void g(void) { _Bool Q; struct { unsigned int u_bit :1; } u; #define U (u.ubit) Q = 0; U = 0; // sets both to 0 Q = 1; U = 1; // sets both to 1 Q = 4; U = 4; // sets Q to 1, U to 0 Q = 0.5; U = 0.5; // sets Q to 1, U to 0 Q++; U++; // sets Q to 1; sets U to 1-U Q--; U--; // sets Q to 1-Q; sets U to 1-U } Jan ----- Original Message --------------- Subject: Re: [sdcc-devel] Separate _Bool from bit? From: Borut Razem <bor...@si...> Date: Fri, 22 Jan 2010 07:49:43 +0100 To: Development chatter about sdcc <sdc...@li...> >I have to explain my statement: I was thinking and writing what is >possible to do for sdcc 3.0 release, so "not applicable" should be read >as "not feasible for 3.0 release". > >Jan is absolutely right: bit addressing is possible and many compilers >are already using it. Usually it is implemented as (<byte address> * 8 + ><bit position in byte>). Actually also the mcs51 sdcc target is using it >internally. > >Using the __bit type in the structure or union could be implemented >using bit fields: > >struct { > int a; > __bit b; > __bit c; > char b; >} s; > >can be internally represented as: > >struct { > int a; > int b :1; > int c :1; > char b; >} s; > >But I doubt that we can "enhance" the __bit handling that it can be used >as _Boolean, so I propose to implement _Boolean as char for sdcc 3.0. If >somebody is willing to start working on __bit handling enhancements >before 3.0 release, we can create a svn branch. > > >Borut > > >Borut Razem wrote: >> I agree too. >> __bit could be also implemented on pic targets, since they have direct >> bit manipulaution instructions. I don't know about hc08. >> >> _Bool should probably be implemented as byte, since there should be a >> possibility to take the address of _Bool variable and make it a >> structure member, which is not applicable with __bit type. >> >> Borut >> >> >> >> Sébastien Lorquet wrote: >> >>> Personally, I totally agree with you. >>> For me, __bit should be a platform specific feature for mcus that >>> provide individual bit storage such as the mcs51, and _Bool should be >>> a standard C type supporting all std operations. >>> >>> Regards >>> Sebastien >>> |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 10:27:49
|
Jan Waclawek wrote: > Borut, > > First, the organisational side of the problem. > >> But I doubt that we can "enhance" the __bit handling that it can be >> used as _Boolean, so I propose to implement _Boolean as char for >> sdcc 3.0. > > I suppose, you mean _Bool (the standard boolean type) to occupy a > whole byte, being addressed/(de)referenced in the same way as > uint8_t; but with properties (conversion/assignment, arithmetics (see > (*)) . I also suppose a regression suite will be created > simultaneously. Well, my plan was this: _Bool occupies one byte, when casting to _Bool we do the test for non-zeroness and set the result to 1 or 0. This is the only required special case for _Bool. Then the bool can be directly used in any arithmetic expression without a further cast. When reading a _Bool, we either treat it as if we would read a byte or read just the lowest bit. This should give a correct implementation of _Bool. > > --- > > Now, two technicalities, both illustrated by a snippet of code from > Derek Jones's book (page 489, "verse" 474, chapter 6.2.5): > > 1. (*) - conforming arithmetics of _Bool is not trivial, regardless > of if it is implemented as a bit or a byte: extern _Bool E; > > void f(void) { if (((E ? 1 : 0) != (!(!E))) || ((E += 2) != 1) || > ((--E, --E, E) != E)) printf("This is not a conforming > implementation\n"); } Should work with my plan. Philipp |
From: Jan W. <we...@ef...> - 2010-01-22 11:14:06
|
>Well, my plan was this: _Bool occupies one byte, when casting to _Bool >we do the test for non-zeroness and set the result to 1 or 0. This is >the only required special case for _Bool. Then the bool can be directly >used in any arithmetic expression without a further cast. When reading a >_Bool, we either treat it as if we would read a byte or read just the >lowest bit. >This should give a correct implementation of _Bool. That sounds cheap enough. Can you please comment also on my suggestion to NOT call this implementation a _Bool natively? Jan |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 11:50:41
|
Jan Waclawek wrote:ither; but as a > non-developer, I might be completely wrong. > > What I see as a major drawback in this approach is, that this gives > the impression to the users that the implementation of _Bool to > occupy a byte is the final solution. They might then be tempted to > (ab)use the (fundamentally incorrect) assumption that pointer of > _Bool can be freely converted to any other pointer type; and codebase > created with this assumption might later, when moving to true bits, > fail. Well, IMO for the Z80 port the implementation of _Bool using a byte will be final. It do not know about the other ports. > > So, here is my proposal as a compromise: let's NOT fix _Bool as a > keywork implemented directly in SDCC. Let's implement the byte-bool > with a yet another SDCC-specific keyword - say, "__bytebool", or any > other; let's properly document both this and __bit, listing both the > advantages and disadvantages and the current state of things; and > then let the user decide, which one she wants to use as _Bool, using > a proper #define. This is for all practical purposes sufficiently > close to the standard, and it allows for a transition time for both > solutions to mature and to gain enough experience with either of > them. Hmm, maybe _Bool could be handled the way sdcc currently handles the sdcc-specific keywords, i.e. enable it only for some ports. Then we would have _Bool on Z80/GBZ80 only and the other ports would continue to either have none or __bit only. Philipp |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 14:39:43
|
Borut Razem wrote: > I have to explain my statement: I was thinking and writing what is > possible to do for sdcc 3.0 release, so "not applicable" should be read > as "not feasible for 3.0 release". > > Jan is absolutely right: bit addressing is possible and many compilers > are already using it. Usually it is implemented as (<byte address> * 8 + > <bit position in byte>). Actually also the mcs51 sdcc target is using it > internally. Unfortunately I do not know as much about C as I wish I would, so I have to go through the standard searching for things that might clarify the situation and ask the list about them. So on one hand we have 1119 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. 1120 The size is determined from the type of the operand. 1121 The result is an integer. Thus sizeof(_Bool) >= 1. and 571 Values stored in unsigned bit-fields and objects of type unsigned char shall be represented using a pure binary notation.40) 572 Values stored in non-bit-field objects of any other object type consist of n × CHAR_BIT bits, where n is the size of an object of that type, in bytes. and 305 Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign. 306 14) See “future language directions” (6.11.3). 307 — number of bits for smallest object that is not a bit-field (byte) CHAR_BIT 8 This looks like the standard _requires_ at least 8 bits per _Bool. On the other hand bit-addressable memory seems to be a way to make using just one bit per _Bool transparent to the user. Philipp P.S.: IMO C should remove the sizeof(char) == 1 requirement. It would solve multiple issues with odd archtiectures. However in sdcc we should aim for standard compliance. |
From: Maarten B. <sou...@ds...> - 2010-01-22 13:16:32
|
Hi all, Some comments. > Jan is absolutely right: bit addressing is possible and many compilers > are already using it. Usually it is implemented as (<byte address> * 8 + > <bit position in byte>). Actually also the mcs51 sdcc target is using it > internally. Allthough SDCC does not support taking the address of a __bit, it could be implemented for the mcs51. There are upto 128 addresses in bitspace and they can be converted to a byte address and a bit position. A new support routine could read and write such a bit pointer. And it could also be stored in a generic pointer as there are still unused ranges. So using bit pointers (and arrays) is possible though it could get inefficient on the mcs51. On the Z80 however I think it's best to keep _Bool in a byte. Then the generic pointer needs no enlargement and one can even cast *_Bool to *char even though it doesn't need to work according to the standard. > Using the __bit type in the structure or union could be implemented > using bit fields: > > struct { > int a; > __bit b; > __bit c; > char b; > } s; > > can be internally represented as: > > struct { > int a; > int b :1; > int c :1; > char b; > } s; Now here is a bigger problem for the mcs51 if we want _Bool to stay the same as __bit, because this struct can be anywhere but the bit must lie in bit-addressable space. We could make all sorts of special handling when it is in a struct, but once the address of a __bit member is taken the pointer no longer knows about that. The only solution I can see is to make two kinds of __bit pointers. One pointing to bitspace and occupying 1 byte which can be cast to generic pointer type A and one that probably only exists as generic pointer type B and even then stays problematic. The two pointer types cannot be assigned to one another. In general I think it's wiser to keep __bit separate from _Bool if we strive for standards conformance and not allow __bit in structs (and pointers and arrays?). Maybe allow __bit to be used like a storage class when used with _Bool. E.g. __bit a; // a boolean in bitspace _Bool b; // a boolean in default memory __bit _Bool c; // a boolean in bitspace __data _Bool d; // a boolean in data memory __bit char e; // illegal or equal to __bdata char? __data __bit f; // illegal > But I doubt that we can "enhance" the __bit handling that it can be used > as _Boolean, so I propose to implement _Boolean as char for sdcc 3.0. If > somebody is willing to start working on __bit handling enhancements > before 3.0 release, we can create a svn branch. > > > Borut > > > Borut Razem wrote: > > I agree too. > > __bit could be also implemented on pic targets, since they have direct > > bit manipulaution instructions. I don't know about hc08. > > > > _Bool should probably be implemented as byte, since there should be a > > possibility to take the address of _Bool variable and make it a > > structure member, which is not applicable with __bit type. > > > > Borut > > > > > > > > Sébastien Lorquet wrote: > > > >> Personally, I totally agree with you. > >> For me, __bit should be a platform specific feature for mcus that > >> provide individual bit storage such as the mcs51, and _Bool should be > >> a standard C type supporting all std operations. > >> > >> Regards > >> Sebastien |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 14:16:52
|
Maarten Brock wrote: > Hi all, > > Some comments. > >> Jan is absolutely right: bit addressing is possible and many compilers >> are already using it. Usually it is implemented as (<byte address> * 8 + >> <bit position in byte>). Actually also the mcs51 sdcc target is using it >> internally. > > Allthough SDCC does not support taking the address of a __bit, it > could be implemented for the mcs51. There are upto 128 addresses in > bitspace and they can be converted to a byte address and a bit > position. A new support routine could read and write such a bit > pointer. And it could also be stored in a generic pointer as there > are still unused ranges. So using bit pointers (and arrays) is > possible though it could get inefficient on the mcs51. > > [...] > >> Using the __bit type in the structure or union could be implemented >> using bit fields: >> >> struct { >> int a; >> __bit b; >> __bit c; >> char b; >> } s; >> >> can be internally represented as: >> >> struct { >> int a; >> int b :1; >> int c :1; >> char b; >> } s; > > Now here is a bigger problem for the mcs51 if we want _Bool to stay > the same as __bit, because this struct can be anywhere but the bit > must lie in bit-addressable space. We could make all sorts of > special handling when it is in a struct, but once the address of a > __bit member is taken the pointer no longer knows about that. The > only solution I can see is to make two kinds of __bit pointers. One > pointing to bitspace and occupying 1 byte which can be cast to > generic pointer type A and one that probably only exists as generic > pointer type B and even then stays problematic. The two pointer > types cannot be assigned to one another. Would it be possible to handle _Bool different depending on it being inside/outside a struct? Use byte-wide _Bools inside structs (if the users cared about saving RAM they would have used a bitfield). _Bool pointers then, since they would have to know, would be the same size as generic pointers? Philipp |
From: Jan W. <we...@ef...> - 2010-01-22 22:12:28
|
Maarten, > Now here is a bigger problem for the mcs51 if we want _Bool to stay > the same as __bit, [...] Unfortunately, it appears, that the current draft of C99 - and also that of the future C1X - specifically *require* _Bool to occupy a (multiple of) byte... So, I would suggest to try to implement _Bool as a byte in the '51 port, too - I have no idea whether Philipp can make his modifications more generic and easily applicable for all other ports, too...? It would then be upon the user to chose, whether she wants to use a standard-conforming yet unefficient _Bool, or an efficient (and potentially conforming, too, except this single verse) __bit. > [...] because this struct can be anywhere but the bit > must lie in bit-addressable space. IMHO a __bit (and, taking it further, a __bit-based bitfield - analogous to __Bool-based bitfields) in a struct can still be implemented as a single bit - whether a bit or a byte, it would require a different set of methods to access it anyway, wouldn't it, and I don't believe it would be that inefficient to go for the single bit on '51 (where RAM is a truly precious resource). > The only solution I can see is to make two kinds of __bit pointers. One > pointing to bitspace and occupying 1 byte which can be cast to > generic pointer type A and one that probably only exists as generic > pointer type B and even then stays problematic. The two pointer > types cannot be assigned to one another. That would make using it almost impossible. Say, if you would want to use the pointer to pass a __bit parameter to and from a function - how would the function know, with which type of pointer to __bit was it envoked? On the other hand, is there a real requirement to keep the pointer to __bit short? Couldn't it simply be big enough to describe *any* bit address, say, 3 bytes (that would perhaps cover also different memory classes)? How often would such a pointer be used, anyway? OK, I have limited experience, but even then - I simply cannot come up with any realistic example which NEEDS to use pointers to __bit as such... I would definitively oppose __bit to be seen as a storage class. I regrettably admit I don't have the skills to support this by implementing the routines needed to make __bit be efficient type, fulfilling all the requirements put on _Bool. Jan |
From: Maarten B. <sou...@ds...> - 2010-01-23 09:39:59
|
Hi Jan, > > The only solution I can see is to make two kinds of __bit pointers. One > > pointing to bitspace and occupying 1 byte which can be cast to > > generic pointer type A and one that probably only exists as generic > > pointer type B and even then stays problematic. The two pointer > > types cannot be assigned to one another. > > That would make using it almost impossible. Say, if you would want to use > the pointer to pass a __bit parameter to and from a function - how would the > function know, with which type of pointer to __bit was it envoked? No, it's not. It's exactly as it is now with pointers to char. If you provide the storage class in the pointer declaration it's a small pointer otherwise it's a generic pointer. void foo(char __idata *iptr, char __xdata *xptr, char *gptr); // iptr takes 1 byte (the address in idata) // xptr takes 2 bytes (the address in xdata) // gptr takes 3 bytes (0x40, 0x00, the address in idata) or // gptr takes 3 bytes (0x00, the address in xdata) Analogous: void bar(_Bool __bit *bptr, _Bool __idata *iptr, _Bool *gptr); // bptr takes 1 byte (the address in bitspace) // iptr takes 1 byte (the address in idata) // gptr takes 3 bytes (0x70, 0x00, the address in bitspace) or // gptr takes 3 bytes (0x40, 0x00, the address in idata) > On the other hand, is there a real requirement to keep the pointer to __bit > short? Couldn't it simply be big enough to describe *any* bit address, say, > 3 bytes (that would perhaps cover also different memory classes)? How often > would such a pointer be used, anyway? OK, I have limited experience, but > even then - I simply cannot come up with any realistic example which NEEDS > to use pointers to __bit as such... I think the users would very much like to see the pointer small if possible. And they can always find a NEED ;-) > I would definitively oppose __bit to be seen as a storage class. I > regrettably admit I don't have the skills to support this by implementing > the routines needed to make __bit be efficient type, fulfilling all the > requirements put on _Bool. We could treat it like this: __bit a; // boolean in bitspace (1 bit) __bit _Bool b; // boolean in bitspace (1 bit) _Bool c; // boolean in bitspace (1 bit) __idata _Bool d; // boolean in idata (1 byte) __bit char e; // illegal struct { __bit a; // boolean in non-bit memory space (1 byte) __bit _Bool b; // boolean in non-bit memory space (1 byte) _Bool c; // boolean in non-bit memory space (1 byte) __idata _Bool d; // illegal __bit char e; // illegal } Maarten |
From: Bodo W. <bod...@we...> - 2010-01-24 14:47:55
|
Hi, These are just my EUR 0,02 more as a user of compilers than as a developer of compilers. I'm using Keil C51 since version X2.45 back in the 80s and GCC since the 90s. My interest in SDCC is to create a port for the ZX81 (Z80 with limited register set) some future day when I hope to have much more time than today... I like the idea of __bit as a storage class like __code or _bdata very much. Yes, I really do! This can satisfy both developers and users of SDCC: ports without bit handling capabilities don't accept __bit, and others like the '51 can accept it and implement efficient allocation and code generation. It's the same as __sfr. If some genius developer finds a cool way to use the bit handling instructions of the Z80, this storage class can be added there. To keep pointer sizes small, the bit addressable space can be limited and shared with other spaces. This is already the case in the '51 port. The address of the bit space can be allocated in the linking stage. It should be acceptable to limit the usability of the storage class __bit, so that arrays, pointers and such complicated stuff can be excluded. Just another note; the address space for bit addresses on the '51 is 256 big. It's true, 128 of them are in RAM and can be used for variables. But the other 128 addresses are bits in the bitaddressable SFRs. I never understood why Keil can't handle "static" on sbit, and I'd like to write generic routines that can use "extern bit PortBit;" (or "extern __bit _Bool Portbit;") and to let the linker resolve the address. Both issues would make SDCC stand out from commercial compilers. Thanks for reading, Bodo |
From: Jan W. <we...@ef...> - 2010-01-25 08:27:12
|
>I like the idea of __bit as a storage class like __code or _bdata very much. Well... The idea itself is really good. However, I would NOT use the __bit keyword for this purpose. The current status (roughly) is, that __bit works for all practical purposes as a type. In fact it hides in itself an implicit storage class specifier, but the user does not need to be aware of it. Maartens proposal would give __bit a double meaning: a type AND a storage class specifier. IMHO, that might get confusing pretty soon. Changing completely the meaning of __bit to storage class specifier would break backward compatibility (and also the "slight" compatibility to Keil and possibly other "competing" compilers). SO, what I would suggest, is to introduce a *new* keyword for the bits storage class - say, "__bits", and retain __bit's current meaning (i.e. the type with implicit placement in the bit addressable area, with possible extensions in the future - e.g. implement __bit in struct occupying a single bit as a :1 bitfield would do, but with boolean behaviour). I would also suggest _Bool without this specifier to define a byte-wide variable, as the standard requires it. JW |
From: Philipp K. K. <pk...@sp...> - 2010-01-25 08:25:14
|
Jan Waclawek schrieb: > It would then be upon the user to chose, whether she wants to use a > standard-conforming yet unefficient _Bool, or an efficient (and potentially > conforming, too, except this single verse) __bit. There's more to efficiency than those few bits of RAM a _Bool might or might not need. Having implemented _Bool on the Z80 now there are clear advantages to using _Bool over unsigned char. The backend can use the knowledge that the _Bool will always contain 0 or 1 to generate faster, more compact code (more about this in an upcoming mail to sdcc-user). Philipp |
From: Philipp K. K. <pk...@sp...> - 2010-01-22 09:36:31
|
Borut Razem wrote: > I have to explain my statement: I was thinking and writing what is > possible to do for sdcc 3.0 release, so "not applicable" should be read > as "not feasible for 3.0 release". > > Jan is absolutely right: bit addressing is possible and many compilers > are already using it. Usually it is implemented as (<byte address> * 8 + > <bit position in byte>). Actually also the mcs51 sdcc target is using it > internally. But what about the problem of generic pointers? Wouldn't that require special-case handling in many places, and for some architectures, like the Z80 increase pointer size? The follwoing applies to the Z80, it might or might not apply to other architectures supported by sdcc. Assume, that we have 8 _Bools in bytes A and B, e.g. _Bool A[8], B[8]; Now, since sizeof(_Bool) has to be at least one, we get sizeof(A) == sizeof(B) == 8. Thus someone might write the following code: memcpy(A, B, 8); to copy from B to A. Now memcpy internally would have to recognize that B is a pointer to _Bool and then copy only one byte instead of eight. For values that are not multiples of eight it would have to copy partial bytes. IMO all these problems make implementing bit-addressable memory undesirable on architectures that have no or insufficient hardware support. Philipp |
From: Sébastien L. <sq...@gm...> - 2010-01-22 09:49:15
|
Or just extend the C syntax so that sizeof(__bit) can return 1/8 :-] or a new operator sizeof_in_bits, a new function memcpy_bits, etc :-] Seriously, I think we found enough problems to avoid making __bit a generic C-standard compatible feature, don't you? Why not keep it a sdcc extension, just like other __ starting keywords for mem spaces, and keep _Bool ~ char ? Sebastien On Fri, Jan 22, 2010 at 10:36 AM, Philipp Klaus Krause <pk...@sp...> wrote: > Borut Razem wrote: > > I have to explain my statement: I was thinking and writing what is > > possible to do for sdcc 3.0 release, so "not applicable" should be read > > as "not feasible for 3.0 release". > > > > Jan is absolutely right: bit addressing is possible and many compilers > > are already using it. Usually it is implemented as (<byte address> * 8 + > > <bit position in byte>). Actually also the mcs51 sdcc target is using it > > internally. > > But what about the problem of generic pointers? Wouldn't that require > special-case handling in many places, and for some architectures, like > the Z80 increase pointer size? > > The follwoing applies to the Z80, it might or might not apply to other > architectures supported by sdcc. > > Assume, that we have 8 _Bools in bytes A and B, e.g. > _Bool A[8], B[8]; > > Now, since sizeof(_Bool) has to be at least one, we get sizeof(A) == > sizeof(B) == 8. > > Thus someone might write the following code: > > memcpy(A, B, 8); > > to copy from B to A. Now memcpy internally would have to recognize that > B is a pointer to _Bool and then copy only one byte instead of eight. > For values that are not multiples of eight it would have to copy partial > bytes. > > IMO all these problems make implementing bit-addressable memory > undesirable on architectures that have no or insufficient hardware support. > > Philipp > > > ------------------------------------------------------------------------------ > Throughout its 18-year history, RSA Conference consistently attracts the > world's best and brightest in the field, creating opportunities for > Conference > attendees to learn about information security's most important issues > through > interactions with peers, luminaries and emerging and established companies. > http://p.sf.net/sfu/rsaconf-dev2dev > _______________________________________________ > sdcc-devel mailing list > sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-devel > |
From: Jan W. <we...@ef...> - 2010-01-22 10:24:37
|
>But what about the problem of generic pointers? Wouldn't that require >special-case handling in many places, and for some architectures, like >the Z80 increase pointer size? No, it wouldn't. A generic pointer to bit is the same issue as a generic pointer to any other object. The issue with address space mentioned in your other ("lost") post IS an issue, though. I have no simple answer at this point; as a naive approach assume that all _Bool-s have to reside within a 8kB segment. Generally, pointer size and address space size is always an issue, and this should perhaps be discussed separately (e.g. several '51 derivatives - some already supported by SDCC - have >64kB native address space already, and this IS already an issue). Conversion to *void is not an issue - there is NO implication in converting such *void to any OTHER type of pointer, so this is purely a formal requirement. >The follwoing applies to the Z80, it might or might not apply to other >architectures supported by sdcc. > >Assume, that we have 8 _Bools in bytes A and B, e.g. >_Bool A[8], B[8]; > >Now, since sizeof(_Bool) has to be at least one, we get sizeof(A) == >sizeof(B) == 8. No, this is not true. 6.5.3.4 clearly states, that "When applied to an operand that has array type, the result is the total number of bytes in the array." memcopy using such sizeof would Taking sizeof() of a _Bool-containing object or type shall most probably issue a warning anyway; and we shall probably provide extended functions with bit-wise size/address/offset taking allowing unambiguous access. >Thus someone might write the following code: > >memcpy(A, B, 8); Which is entirely foolish to write. memcpy() is a *string* handling function, copying *characters* (not even bytes!); it is not reasonable to expect that it will know how to handle _Bool arrays correctly. We can of course provide a library of equivalent but appropriately written _Bool manipulation utilities. Jan |