increase alignment of global structs in increase_alignment pass
Hi Richard, As discussed in private mail, this version of patch attempts to increase alignment of global struct decl if it contains an an array field(s) and array's offset is a multiple of the alignment of vector type corresponding to it's scalar type and recursively checks for nested structs. eg: static struct { int a, b, c, d; int k[4]; float f[10]; }; k is a candidate array since it's offset is 16 and alignment of "vector (4) int" is 8. Similarly for f. I haven't been able to create a test-case where there are multiple candidate arrays and vector alignment of arrays are different. I suppose in this case we will have to increase alignment of the struct by the max alignment ? eg: static struct { T1 k[S1] T2 f[S2] }; if V1 is vector type corresponding to T1, and V2 corresponding vector type to T2, offset (k) % align(V1) == 0 and offset (f) % align(V2) == 0 and align (V1) > align(V2) then we will increase alignment of struct by align(V1). Testing showed FAIL for g++.dg/torture/pr31863.C due to program timeout. Initially it appeared to me, it went in infinite loop. However on second thoughts I think it's probably not an infinite loop, rather taking (extraordinarily) large amount of time to compile the test-case with the patch. The test-case builds quickly for only 2 instantiations of ClassSpec (ClassSpec, ClassSpec) Building with 22 instantiations (upto ClassSpec) takes up to ~1m to compile. with: 23 instantiations: ~2m 24 instantiations: ~5m For 30 instantiations I terminated cc1plus after 13m (by SIGKILL). I guess it shouldn't go in an infinite loop because: a) structs cannot have circular references. b) works for lower number of instantiations However I have no sound evidence that it cannot be in infinite loop. I don't understand why a decl node is getting visited more than once for that test-case. Using a hash_map to store alignments of decl's so that decl node gets visited only once prevents the issue. The patch is cross-tested on aarch64*-*-* and arm*-*-* and passes with using hash_map workaround. Thanks, Prathamesh diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 2b25b45..6f8c3b6 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -794,38 +794,112 @@ make_pass_slp_vectorize (gcc::context *ctxt) This should involve global alignment analysis and in the future also array padding. */ +static unsigned get_vec_alignment_for_decl (tree); + +/* FIXME: decl_align_map is used to cache vec alignments of decl nodes, + so if a decl node is visited again, get_vec_alignment_for_decl + returns the alignment. + This is done to avoid looping infinitely or taking + very large time to compile for pr31863.C (and similar cases). + This happens because a decl node gets visited multiple times. + I am not sure why a decl node gets visited multiple times. */ +static hash_map *decl_align_map; + +static unsigned +get_vec_alignment_for_array_decl (tree array_decl) +{ + tree type = TREE_TYPE (array_decl); + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + + tree vectype = get_vectype_for_scalar_type (strip_array_types (type)); + return (vectype) ? TYPE_ALIGN (vectype) : 0; +} + +static unsigned +get_vec_alignment_for_record_decl (tree record_decl) +{ + tree type = TREE_TYPE (record_decl); + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + unsigned max_align = 0, alignment; + HOST_WIDE_INT offset; + + if (TYPE_PACKED (type)) +return 0; + + for (tree field = first_field (type); field != NULL_TREE; field = DECL_CHAIN (field)) +{ + /* C++FE puts node "._0" of code TYPE_DECL. skip that. */ + if (TREE_CODE (field) != FIELD_DECL) + continue; + + offset = int_byte_position (field); + alignment = get_vec_alignment_for_decl (field); + if (alignment && (offset % (alignment / BITS_PER_UNIT) == 0) && (alignment > max_align)) + max_align = alignment; +} + + return max_align; +} + +static unsigned +get_vec_alignment_for_decl (tree decl) +{ + if (decl == NULL_TREE) +return 0; + + gcc_assert (DECL_P (decl)); + + unsigned *slot = decl_align_map->get (decl); + if (slot) +return *slot; + + static unsigned alignment = 0; + tree type = TREE_TYPE (decl); + + switch (TREE_CODE (type)) +{ + case ARRAY_TYPE: + alignment = get_vec_alignment_for_array_decl (decl); + break; + case RECORD_TYPE: + alignment = get_vec_alignment_for_record_decl (decl); + break; + default: + alignment = 0; + break; +} + + unsigned ret = (alignment > DECL_ALIGN (decl)) ? alignment : 0; + decl_align_map->put (decl, ret); + return ret; +} + static unsigned int increase_alignment (void) { varpool_node *vnode; vect_location = UNKNOWN_LOCATION; - + decl_align_map = new hash_map; + /* Increase the alignment of all global arrays for vectorization. */ FOR_EACH_DEFINED_VARIABLE (vnode) { tree vectype, decl = vnode->decl; - tree
section type conflict in gcc xtensa
Dear Sir, We are getting the following error "section type conflict" with xtensa gcc when a const and non const global variable is placed in the same section? I am using a bare metal cross gcc toolchain for Xtensa architecture built as per instructions in http://wiki.linux-xtensa.org/index.php/Crosstool-NG. We are using a custom Xtensa processor in our firmware. For example consider the code below __attribute__((section(".dram0.data"))) int x; __attribute__((section(".dram0.data"))) const int y = 10; main() { } This throws up an error during compilation test3.c:2:51: error: y causes a section type conflict with x __attribute__((section(".dram0.data"))) const int y = 10; ^ test3.c:1:45: note: ‘x’ was declared here __attribute__((section(".dram0.data"))) int x; Removing the const attribute for y will remove this error. We built our firmware by removing const attributes.Firmware built using xcc works fine but the same code built using gcc works partly Thanks and Regards Hari
Re: section type conflict in gcc xtensa
On Mon, Feb 22, 2016 at 02:57:43PM +0530, Hari Narasimhan H.N wrote: > Dear Sir, > > We are getting the following error "section type conflict" with xtensa > gcc when a const and non const global variable is placed in the same > section? > > I am using a bare metal cross gcc toolchain for Xtensa architecture > built as per instructions in > http://wiki.linux-xtensa.org/index.php/Crosstool-NG. We are using a > custom Xtensa processor in our firmware. > > For example consider the code below > > __attribute__((section(".dram0.data"))) int x; > __attribute__((section(".dram0.data"))) const int y = 10; This is user error. You really shouldn't mix const and non-const variables in the same section, the non-const vars want a writable section, while the const ones (unless they need dynamic relocations) want read-only section. Put them into separate sections, and perhaps through a linker script combine them together if you for whatever strange reason need that. Jakub
Re: increase alignment of global structs in increase_alignment pass
On Mon, 22 Feb 2016, Prathamesh Kulkarni wrote: > Hi Richard, > As discussed in private mail, this version of patch attempts to > increase alignment > of global struct decl if it contains an an array field(s) and array's > offset is a multiple of the alignment of vector type corresponding to > it's scalar type and recursively checks for nested structs. > eg: > static struct > { > int a, b, c, d; > int k[4]; > float f[10]; > }; > k is a candidate array since it's offset is 16 and alignment of > "vector (4) int" is 8. > Similarly for f. > > I haven't been able to create a test-case where there are > multiple candidate arrays and vector alignment of arrays are different. > I suppose in this case we will have to increase alignment > of the struct by the max alignment ? > eg: > static struct > { > > T1 k[S1] > > T2 f[S2] > > }; > > if V1 is vector type corresponding to T1, and V2 corresponding vector > type to T2, > offset (k) % align(V1) == 0 and offset (f) % align(V2) == 0 > and align (V1) > align(V2) then we will increase alignment of struct > by align(V1). > > Testing showed FAIL for g++.dg/torture/pr31863.C due to program timeout. > Initially it appeared to me, it went in infinite loop. However > on second thoughts I think it's probably not an infinite loop, rather > taking (extraordinarily) large amount of time > to compile the test-case with the patch. > The test-case builds quickly for only 2 instantiations of ClassSpec > (ClassSpec, > ClassSpec) > Building with 22 instantiations (upto ClassSpec) takes up > to ~1m to compile. > with: > 23 instantiations: ~2m > 24 instantiations: ~5m > For 30 instantiations I terminated cc1plus after 13m (by SIGKILL). > > I guess it shouldn't go in an infinite loop because: > a) structs cannot have circular references. > b) works for lower number of instantiations > However I have no sound evidence that it cannot be in infinite loop. > I don't understand why a decl node is getting visited more than once > for that test-case. > > Using a hash_map to store alignments of decl's so that decl node gets visited > only once prevents the issue. Maybe aliases. Try not walking vnode->alias == true vars. Richard.
Re: RFC: Update Intel386, x86-64 and IA MCU psABIs for passing/returning empty struct
Hi, On Fri, 19 Feb 2016, Richard Smith wrote: > >> > The trivially copyable is gone again. Why is it not necessary? > >> > >> The C++ ABI doesn't defer to the C psABI for types that aren't > >> trivially-copyable. See > >> http://mentorembedded.github.io/cxx-abi/abi.html#normal-call > > > > Hmm, yes, but we don't want to define something for only C and C++, but > > language independend (so far as possible). And given only the above > > language I think this type: > > > > struct S { > > S() {something();} > > }; > > > > would be an empty type, and that's not what we want. > > Yes it is. Did you mean to give S a copy constructor, copy assignment > operator, or destructor instead? Er, yes, I did mean to :-) Ciao, Michael.
Re: RFC: Update Intel386, x86-64 and IA MCU psABIs for passing/returning empty struct
Hi, On Sat, 20 Feb 2016, Richard Smith wrote: > > An empty type is a type where it and all of its subobjects > > (recursively) are of class, structure, union, or array type. > > > > doesn't cover "trivially-copyable". > > That's correct. Whether a type is trivially copyable is unrelated to > whether it is empty. I would still feel more comfortable to include the restriction to trivially copyable types, not in the part of definition of empty type, of course, but as part of the restrictions of when a type can be passed in no registers. Basically to clarify the intent in the psABI if there's any doubt. I.e. like so: --- An empty type is a type where it and all of its subobjects (recursively) are of class, structure, union, or array type. No memory slot nor register should be used to pass or return an object of empty type that's trivially copyable. --- (With possibly a self-sufficient definition of trivially copyable, that's language agnostic) Ciao, Michael.
extendqihi2 and GCC RTL type system
csmith has uncovered a latent bug in the the PowerPC port for a combiner pattern involving extendqihi2 (the alternative in the pattern has never triggered for real code in over 10 years). Basic extendqihi2 works correctly (the instructions extend to entire register, but the upper bits are ignored). The PowerPC architecture can load and store HImode values, but cannot compute directly on that mode -- only on SImode or DImode. One proposed fix for the bug would remove extendqihi2, forcing GCC to use SUBREGs for HImode extend operations, as it does for all other computations. If I remove extendqihi2 (extend:HI pattern) from the PowerPC port, will that cause any problems for the GCC RTL type system or inhibit optimizations? I see that Alpha and SPARC define extendqihi2, but IA-64 and AArch64 do not, so there is precedent for both approaches. Any insights would be appreciated. Thanks, David
Re: extendqihi2 and GCC RTL type system
On 02/22/2016 08:55 AM, David Edelsohn wrote: csmith has uncovered a latent bug in the the PowerPC port for a combiner pattern involving extendqihi2 (the alternative in the pattern has never triggered for real code in over 10 years). Basic extendqihi2 works correctly (the instructions extend to entire register, but the upper bits are ignored). The PowerPC architecture can load and store HImode values, but cannot compute directly on that mode -- only on SImode or DImode. Right. Similar to the PA in that regard. One proposed fix for the bug would remove extendqihi2, forcing GCC to use SUBREGs for HImode extend operations, as it does for all other computations. And that should work. If I remove extendqihi2 (extend:HI pattern) from the PowerPC port, will that cause any problems for the GCC RTL type system or inhibit optimizations? I see that Alpha and SPARC define extendqihi2, but IA-64 and AArch64 do not, so there is precedent for both approaches. Any insights would be appreciated. It shouldn't cause any type system kinds of problems. It might cause missed optimizations though. I'm not sure if combine will handle optimizing away the SUBREG by exploiting LOAD_EXTEND_OP. Jeff
David Malcolm appointed libcpp and diagnostic messages maintainer
I am pleased to announce that the GCC Steering Committee has appointed David Malcolm as libcpp and diagnostic messages maintainer. Please join me in congratulating David on his new role. David, please update your listing in the MAINTAINERS file. Happy hacking! David
Re: David Malcolm appointed libcpp and diagnostic messages maintainer
On Mon, 2016-02-22 at 11:14 -0500, David Edelsohn wrote: > I am pleased to announce that the GCC Steering Committee has > appointed David Malcolm as libcpp and diagnostic messages maintainer. > > Please join me in congratulating David on his new role. > David, please update your listing in the MAINTAINERS file. > > Happy hacking! > David Thanks! I've committed the attached as r233608. Index: ChangeLog === --- ChangeLog (revision 233607) +++ ChangeLog (working copy) @@ -1,3 +1,8 @@ +2016-02-22 David Malcolm + + * MAINTAINERS (libcpp): Add myself. + (diagnostic messages): Likewise. + 2016-02-20 Tom de Vries * MAINTAINERS: Fix whitespace. Index: MAINTAINERS === --- MAINTAINERS (revision 233607) +++ MAINTAINERS (working copy) @@ -164,6 +164,7 @@ libbacktrace Ian Lance Taylor libcpp Per Bothner libcpp All C and C++ front end maintainers +libcpp David Malcolm fp-bit Ian Lance Taylor libdecnumber Ben Elliston libgcc Ian Lance Taylor @@ -217,6 +218,7 @@ i18n Philipp Thomas i18n Joseph Myers diagnostic messages Dodji Seketeli +diagnostic messages David Malcolm build machinery (*.in) Paolo Bonzini build machinery (*.in) DJ Delorie build machinery (*.in) Nathanael Nerode
Re: extendqihi2 and GCC RTL type system
On Mon, Feb 22, 2016 at 7:55 AM, David Edelsohn wrote: > If I remove extendqihi2 (extend:HI pattern) from the PowerPC port, > will that cause any problems for the GCC RTL type system or inhibit > optimizations? I see that Alpha and SPARC define extendqihi2, but > IA-64 and AArch64 do not, so there is precedent for both approaches. aarch64 does have an extendqihi2 pattern. It uses so many iterator macros that you can't use grep to look for stuff. The extendqihi2 pattern is called qihi2. If you have a target with registers larger than HImode, no HImode register operations, qi/hi loads set the entire register, and you define PROMOTE_MODE to convert all QImode and HImode operations to the same larger mode with the same signedness, then I don't think that there is any advantage to having an extendqihi2 pattern. You should get the same code with or without it, as a qimode to himode conversion is a no-op. The only difference should be that with an extendqihi2 pattern you will see some HImode operations in the RTL, without extendqihi2 you will see equivalent operations in the promoted mode. If you are concerned about this, then just try compiling some large code base using two compilers, one with extendqihi2 and one without, and check to see if there are any code generation differences. Jim
Re: extendqihi2 and GCC RTL type system
Hi, Jim On Mon, Feb 22, 2016 at 12:53 PM, Jim Wilson wrote: > On Mon, Feb 22, 2016 at 7:55 AM, David Edelsohn wrote: >> If I remove extendqihi2 (extend:HI pattern) from the PowerPC port, >> will that cause any problems for the GCC RTL type system or inhibit >> optimizations? I see that Alpha and SPARC define extendqihi2, but >> IA-64 and AArch64 do not, so there is precedent for both approaches. > > aarch64 does have an extendqihi2 pattern. It uses so many iterator > macros that you can't use grep to look for stuff. The extendqihi2 > pattern is called qihi2.\ Thanks for the response. I had missed the all-encompassing iterator for qidi2. > If you have a target with registers larger than HImode, no HImode > register operations, qi/hi loads set the entire register, and you > define PROMOTE_MODE to convert all QImode and HImode operations to the > same larger mode with the same signedness, then I don't think that > there is any advantage to having an extendqihi2 pattern. You should > get the same code with or without it, as a qimode to himode conversion > is a no-op. The only difference should be that with an extendqihi2 > pattern you will see some HImode operations in the RTL, without > extendqihi2 you will see equivalent operations in the promoted mode. > > If you are concerned about this, then just try compiling some large > code base using two compilers, one with extendqihi2 and one without, > and check to see if there are any code generation differences. Segher did a quick sniff test on a large code base and found two minor differences in code generation. I wanted to check if there was any more information than anecdotes. Thanks, David
Re: Help about how to bootstrap gcc with local version glibc other than system one
On Mon, Feb 1, 2016 at 7:45 PM, Jeff Law wrote: > On 02/01/2016 12:07 PM, Bin.Cheng wrote: >> >> On Mon, Feb 1, 2016 at 6:08 PM, Andreas Schwab >> wrote: >>> >>> "Bin.Cheng" writes: >>> Seems to me Andrew was right in comment of PR69559, that we simply couldn't bootstrap GCC with sysroot. >>> >>> >>> The main use of sysroot is to build a cross compiler, which you cannot >>> bootstrap anyway. >>> My question here is: If this is the case, how should I bootstrap a gcc against local version glibc, rather than the system one? Is chroot the only way to do that? >>> >>> >>> Yes, building in a chroot or a VM is the best way to do it. For >>> example, that's how the openSUSE Build Service works. >> >> Hi Andreas, >> Thanks very much for helping. I will try to do it in chroot. > > Definitely what I'd recommend as well. > > We do this regularly with something called "mock" on Fedora. I'm sure SuSE, > Debian, Ubuntu, etc have an equivalent. > > Essentially they create a chroot, populate it with build dependencies > extracted from the source package, then build within the chroot. You can > arrange to get a different glibc during instantiation of the chroot, or > upgrade it after the chroot is fully instantiated. Hi, I still don't quite follow this method. If I pop up chroot environment with new glibc, it's still possible that the new glibc isn't compatible with the default gcc in chroot. Won't this a chicken-egg problem because we want to build our gcc against new glibc in the first place? Thanks, bin > > I'm sure there's a way to do this with containers too. > > jeff
Re: Help about how to bootstrap gcc with local version glibc other than system one
On 02/22/2016 11:52 AM, Bin.Cheng wrote: Hi, I still don't quite follow this method. If I pop up chroot environment with new glibc, it's still possible that the new glibc isn't compatible with the default gcc in chroot. Won't this a chicken-egg problem because we want to build our gcc against new glibc in the first place? If there's a fundamental incompatibility, then you have to bootstrap, similar to bootstrapping a new architecture. That's rarely the case though. Most of the time it's sufficient to use mock or similar tools in this manner to build a new glibc or new gcc. You can then repeat using the just built glibc or gcc to catch any secondary effects. jeff
Re: Need suggestion about bug 68425
On Sun, 21 Feb 2016, Prasad Ghangal wrote: > - pedwarn_init (loc, 0, > -"excess elements in array initializer"); > + pedwarn_init (loc, 0, "excess elements in array initializer " > + "(%lu elements, expected %lu)", > + tree_to_uhwi (constructor_index) + 1, > + tree_to_uhwi (constructor_max_index) + 1); %lu is not correct for HOST_WIDE_INT. You need to use %wu. -- Joseph S. Myers jos...@codesourcery.com
Re: How to use _Generic with bit-fields
I wonder if ISO C really ought to have a new Constraint "The controlling expression of a generic selection shall not be an expression that designates a bit-field member." (so requiring a diagnostic), much like such expressions being disallowed in sizeof, to reflect the special nature of bit-fields and their types in C. Or, more weakly, to allow the cbrt example, "If the controlling expression of a generic selection is an expression that designates a bit-field member, it is unspecified whether the type of that expression is considered compatible with any integer types named in its generic association list.". -- Joseph S. Myers jos...@codesourcery.com
Re: How to use _Generic with bit-fields
On Mon, 22 Feb 2016, Wink Saville wrote: > What about printing of "long" bit fields? I wonder if there should be an > option which indicates that bit field types should not include their length. "long" bit-fields aren't even guaranteed by ISO C to be supported at all; portable code must avoid them. The portable way to print values of arbitrary integer types is to cast to intmax_t / uintmax_t and then use corresponding formats; that works fine with such bit-fields as well as normal types. -- Joseph S. Myers jos...@codesourcery.com
Re: How to use _Generic with bit-fields
I understand "long" bit fields are in ISO, but its a gcc extension so it would seem it should play nice with as much of the language as possible. It seems the root of the problem here is the length encoding in the type, why does gcc do that, does the standard require it? On Mon, Feb 22, 2016 at 3:48 PM, Joseph Myers wrote: > On Mon, 22 Feb 2016, Wink Saville wrote: > >> What about printing of "long" bit fields? I wonder if there should be an >> option which indicates that bit field types should not include their length. > > "long" bit-fields aren't even guaranteed by ISO C to be supported at all; > portable code must avoid them. The portable way to print values of > arbitrary integer types is to cast to intmax_t / uintmax_t and then use > corresponding formats; that works fine with such bit-fields as well as > normal types. > > -- > Joseph S. Myers > jos...@codesourcery.com
Re: How to use _Generic with bit-fields
I'm sorry I meant: I understand "long" bit lengths are NOT in ISO, " On Mon, Feb 22, 2016 at 4:06 PM, Wink Saville wrote: > I understand "long" bit fields are in ISO, but its a gcc extension so > it would seem it should play nice with as much of the language as > possible. > > It seems the root of the problem here is the length encoding > in the type, why does gcc do that, does the standard > require it? > > On Mon, Feb 22, 2016 at 3:48 PM, Joseph Myers wrote: >> On Mon, 22 Feb 2016, Wink Saville wrote: >> >>> What about printing of "long" bit fields? I wonder if there should be an >>> option which indicates that bit field types should not include their length. >> >> "long" bit-fields aren't even guaranteed by ISO C to be supported at all; >> portable code must avoid them. The portable way to print values of >> arbitrary integer types is to cast to intmax_t / uintmax_t and then use >> corresponding formats; that works fine with such bit-fields as well as >> normal types. >> >> -- >> Joseph S. Myers >> jos...@codesourcery.com
Re: How to use _Generic with bit-fields
On Mon, 22 Feb 2016, Wink Saville wrote: > I understand "long" bit fields are in ISO, but its a gcc extension so > it would seem it should play nice with as much of the language as > possible. > > It seems the root of the problem here is the length encoding > in the type, why does gcc do that, does the standard > require it? See the previously identified analysis of the textual history, the various C90 and C99 DRs involved, and how (as noted in 1993 in DR#120, and as is still the case) there is *no definition whatever* in ISO C of what value would be stored in a bit-field by an assignment of a value out of range of an integer type with the given number of bits, other than through the rules for conversions, which only apply if you consider the bit-field to have the restricted-width type. (And, if you wish, you could do the archaeology around the many bugs that were fixed in GCC by giving bit-fields types reflecting the values they could actually represent.) The root of the "problem" is using the extension of bit-fields wider than int, a feature that simply doesn't fit well into the C language and has unintuitive consequences. -- Joseph S. Myers jos...@codesourcery.com
Re: How to use _Generic with bit-fields
On 02/21/2016 06:44 PM, Wink Saville wrote: I've tried you hack, but it doesn't work with "long bit fields". Also, I've run into another problem. Instead of using unsigned char for the bit field I changed it to a long unsigned int:33 and now I can't print it without a warning. That's unfortunate. As I suggested before, it would be useful to add your test cases to bug 65471 to help bring them to the committee's attention. The bug submitter especially seems to be interested in making the feature more useful and while he may not be reading this list he is likely to notice the bug update. The purpose of the generic selection in C is to provide a limited form of function overloading. Calling functions with bitfield arguments is obviously useful regardless of the bit-field width so it should "just work" with _Generic. It does with other compilers (Clang and the EDG front end) and there's no good reason for the C standard not to support it. (The problem is simply that wording that specifies the feature was poorly chosen and GCC seems to follow it a bit too strictly, and to the detriment of usability.) I'm sorry but I can't think of a way to make this work the way you're trying to. Again, I encourage you to add it to the existing bug or open a new one. Martin PS From some of the followups downthread it looks to me as though the problem might be thought to be the bit-field width in your test case exceeding that of int. The following example shows that the same problem error is reported even with a smaller bit-field. $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c struct S { unsigned i: 31; } s; int i = _Generic (s.i, unsigned: 1); z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not compatible with any association int i = _Generic (s.i, unsigned: 1); ^
Re: How to use _Generic with bit-fields
On Mon, 22 Feb 2016, Martin Sebor wrote: > for the C standard not to support it. (The problem is simply that > wording that specifies the feature was poorly chosen and GCC seems > to follow it a bit too strictly, and to the detriment of usability.) The wording for bit-fields, although unclear in places, elegantly addresses all the issues with what the semantics of assignment to bit-fields are (including e.g. allowing an instruction for conversion of floating-point to 16-bit integer, complete with raising exceptions for out-of-range values, to be used to convert to int:16, rather than requiring a conversion to int and subsequent conversion from int to int:16), with none of the duplication that would be involved if bit-fields had the underlying types and so semantics for conversions needed to be specified separately. It also naturally means that e.g. unsigned long:1 promotes to int in expressions, by the normal rules for promotions. > $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc > -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c > struct S { unsigned i: 31; } s; > int i = _Generic (s.i, unsigned: 1); > z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not > compatible with any association > int i = _Generic (s.i, unsigned: 1); >^ That can be avoided simply by using unary + in the controlling expression of _Generic (just as using unary + will avoid an error from sizeof, if you want to be able to apply that to expressions that might be bit-fields) - or any of the other techniques for achieving promotions of selected types. You can't use bit-fields with sizeof, or with unary &, or in GNU C with typeof. I think extending this constraint to _Generic - meaning you need to use a trick such as unary + when a bit-field might occur there - is consistent with the peculiar position of bit-fields in C as not quite normal objects or types (and consistent with how _Generic is intended for certain limited kinds of overloading such as , not for arbitrarily expressive logic on types, cf. the rejection of overloading on qualifiers). If someone uses e.g. unsigned int:8 as the controlling expression of _Generic, it's hardly clear whether a selection for unsigned char (a type with the same set of values), unsigned int (the declared type ignoring width) or int (the type resulting from the integer promotions) would be the most useful selection. -- Joseph S. Myers jos...@codesourcery.com
Re: How to use _Generic with bit-fields
Joseph, Thanks for the unary + suggestion. It definitely makes sense that the bit field length must be known for handling things like assignments, but it doesn't have to be part of the type signature. Martin, I've updated bug 65471: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65471 I created a simpler test program: $ cat test.c #include struct S { int b0:4; unsigned int b1:4; unsigned long long int b33:33; }; #define type2str(__x) _Generic((__x), \ int : "int", \ unsigned int : "unsigned int", \ unsigned long long int : "unsigned long long int", \ default : "unknown") int main(void) { struct S s = { .b0=3, .b1=4, .b33=0x1 }; (void)s; // Not used // gcc | clang output printf("type2str(s.b0): %s\n", type2str(s.b0)); // unknown | int printf("type2str(s.b1): %s\n", type2str(s.b1)); // unknown | unsigned int printf("type2str(s.b33): %s\n", type2str(s.b33));// unknown | unsigned long long int return 0; } $ cat Makefile CC = gcc O = 3 STD = c11 M = 32 test: test.c Makefile $(CC) -O$(O) -m$(M) -Wall -std=$(STD) test.c -o test clean: rm -f test And ran it on gcc and clang $ make clean ; make CC=gcc ; ./test rm -f test gcc -O3 -m32 -Wall -std=c11 test.c -o test type2str(s.b0): unknown type2str(s.b1): unknown type2str(s.b33): unknown $ make clean ;make CC=clang ; ./test rm -f test clang -O3 -m32 -Wall -std=c11 test.c -o test type2str(s.b0): int type2str(s.b1): unsigned int type2str(s.b33): unsigned long long int -- Wink On Mon, Feb 22, 2016 at 4:58 PM, Joseph Myers wrote: > On Mon, 22 Feb 2016, Martin Sebor wrote: > >> for the C standard not to support it. (The problem is simply that >> wording that specifies the feature was poorly chosen and GCC seems >> to follow it a bit too strictly, and to the detriment of usability.) > > The wording for bit-fields, although unclear in places, elegantly > addresses all the issues with what the semantics of assignment to > bit-fields are (including e.g. allowing an instruction for conversion of > floating-point to 16-bit integer, complete with raising exceptions for > out-of-range values, to be used to convert to int:16, rather than > requiring a conversion to int and subsequent conversion from int to > int:16), with none of the duplication that would be involved if bit-fields > had the underlying types and so semantics for conversions needed to be > specified separately. It also naturally means that e.g. unsigned long:1 > promotes to int in expressions, by the normal rules for promotions. > >> $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc >> -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c >> struct S { unsigned i: 31; } s; >> int i = _Generic (s.i, unsigned: 1); >> z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not >> compatible with any association >> int i = _Generic (s.i, unsigned: 1); >>^ > > That can be avoided simply by using unary + in the controlling expression > of _Generic (just as using unary + will avoid an error from sizeof, if you > want to be able to apply that to expressions that might be bit-fields) - > or any of the other techniques for achieving promotions of selected types. > > You can't use bit-fields with sizeof, or with unary &, or in GNU C with > typeof. I think extending this constraint to _Generic - meaning you need > to use a trick such as unary + when a bit-field might occur there - is > consistent with the peculiar position of bit-fields in C as not quite > normal objects or types (and consistent with how _Generic is intended for > certain limited kinds of overloading such as , not for > arbitrarily expressive logic on types, cf. the rejection of overloading on > qualifiers). If someone uses e.g. unsigned int:8 as the controlling > expression of _Generic, it's hardly clear whether a selection for unsigned > char (a type with the same set of values), unsigned int (the declared type > ignoring width) or int (the type resulting from the integer promotions) > would be the most useful selection. > > -- > Joseph S. Myers > jos...@codesourcery.com