Hi Richard,
Thanks! I can confirm that changing VAR_DECL's type
and calling relayout_decl fixes my problem.
On 2020-01-28 4:35 a.m., Richard Biener wrote:
> On Mon, Jan 27, 2020 at 6:41 PM Erick Ochoa
> wrote:
>>
>> Hello,
>>
>> I have a problem with a transformation I'm working on and I would appreciate
>> some help. The transformation I am working on removes fields in structs early
>> during link-time. For the purposes of development and this example, my
>> transformation deletes the field identified as "delete_me" from the struct
>> identified as "astruct_s". These identifiers are hard coded in the
>> transformation at the moment.
>>
>> For example:
>>
>> ```c
>> int
>> main()
>> {
>>struct astruct_s { _Bool a; _Bool delete_me; _Bool c;};
>>// more
>> }
>> ```
>>
>> should be equivalent to
>>
>> ```c
>> int
>> main()
>> {
>>struct astruct_s { _Bool a; _Bool c;};
>>// more
>> }
>> ```
>>
>> as long as no instruction accesses field "delete me".
>>
>> I have succeeded in eliminating field "delete_me" from struct "astruct_s" and
>> at the same time successfully calculating field offsets and array offsets for
>> a subset of the C syntax. I am working on expanding the allowed syntax and at
>> the same time creating tests to verify my assumptions/work is still producing
>> correct results.
>>
>> I was starting work on supporting arrays of multiple dimensions, when I found
>> an interesting edge case in my transformation. I was able to transform
>> structs
>> of size 2, 3, (but not 4), 5, 6, 7, (but not 8), 9, 10... This was the stack
>> trace when the error was triggered:
>>
>> ```
>> a.c: In function ‘main’:
>> a.c:11:19: internal compiler error: in convert_move, at expr.c:219
>>11 | struct astruct_s b = a[argc][argc];
>> | ^
>> 0xb8bac3 convert_move(rtx_def*, rtx_def*, int)
>> /home/eochoa/code/gcc/gcc/expr.c:219
>> 0xb9f5cf store_expr(tree_node*, rtx_def*, int, bool, bool)
>> /home/eochoa/code/gcc/gcc/expr.c:5825
>> 0xb9d913 expand_assignment(tree_node*, tree_node*, bool)
>> /home/eochoa/code/gcc/gcc/expr.c:5509
>> 0xa08bfb expand_gimple_stmt_1
>> /home/eochoa/code/gcc/gcc/cfgexpand.c:3746
>> 0xa09047 expand_gimple_stmt
>> /home/eochoa/code/gcc/gcc/cfgexpand.c:3844
>> 0xa1170f expand_gimple_basic_block
>> /home/eochoa/code/gcc/gcc/cfgexpand.c:5884
>> 0xa134b7 execute
>> /home/eochoa/code/gcc/gcc/cfgexpand.c:6539
>> Please submit a full bug report,
>> ```
>>
>> Looking at expr.c:219 I found the following assertions
>>
>> ```c
>> /* Copy data from FROM to TO, where the machine modes are not the same.
>>Both modes may be integer, or both may be floating, or both may be
>>fixed-point.
>>UNSIGNEDP should be nonzero if FROM is an unsigned type.
>>This causes zero-extension instead of sign-extension. */
>>
>> void
>> convert_move (rtx to, rtx from, int unsignedp)
>> {
>> machine_mode to_mode = GET_MODE (to);
>> machine_mode from_mode = GET_MODE (from);
>>
>> gcc_assert (to_mode != BLKmode);
>> gcc_assert (from_mode != BLKmode); <-- crashes here
>> ```
>>
>> I started reading the gcc internals around machine modes:
>> https://gcc.gnu.org/onlinedocs/gccint/Machine-Modes.html
>> and tried the experiment where I first compiled a struct of size 2 (and
>> delete
>> field "delete_me"), then of size 3 and so on, and so on. I noticed that the
>> TYPE_MODE for matches the machine mode. And that it varies with the size of
>> the
>> struct. (Which agrees with the definition of machine mode.)
>>
>> I originally thought that I needed to set TYPE_MODE myself, but if
>> layout_type
>> is called after deleting the field (which it is), then TYPE_MODE is correctly
>> set somewhere within layout_type:
>> https://github.com/gcc-mirror/gcc/blob/68697710fdd35077e8617f493044b0ea717fc01a/gcc/stor-layout.c#L2203
>> I verified that layout_type is setting the correct values for TYPE_MODE when
>> transforming struct "astruct_s" by comparing the TYPE_MODE of different sizes
>> without the transformation applied. When transforming structs, layout_type
>> always returned a TYPE_MODE which matched the TYPE_MODE for unmodified
>> structs
>> with the same size as the transformed struct (post transformation).
>>
>> In other words:
>>
>> For variable "struct not_transformed b" without transformation I obtain
>> the following relationship. Without transformation:
>>
>> | size | typemode |
>> |--|--|
>> | 1| 13 |
>> | 2| 14 |
>> | 3| 1|
>> | 4| 15 |
>> | 5| 1|
>> | 6| 1|
>> | 7| 1|
>> | 8| 16 |
>> | 9| 1|
>>
>> With transformation (i.e. astruct_s b with a field named "delete_me")
>>
>> | size before | size after | typemode |
>> |-||--|
>> | 2 | 1 | 13 |
>> | 3 | 2 | 14 |
>> | 4 | 3 | 1|
>> | 5