Message ID | BE8F0361-BFCA-44EC-8AF9-1AF7B2FA1B98@comcast.net |
---|---|
State | New |
Headers | show |
On 04.11.2016 03:48, Mike Stump wrote: > On Nov 3, 2016, at 8:25 AM, Georg-Johann Lay <avr@gjlay.de> wrote: >> >> On 28.10.2016 17:58, Mike Stump wrote: >>> On Oct 27, 2016, at 3:16 AM, Georg-Johann Lay <avr@gjlay.de> wrote: >>>> >>>> Now imagine some arithmetic like &&LAB2 - &&LAB1. This might result in >>>> one or two stub addresses, and difference between such addresses is a >>>> complete different thing than the difference between the original labels: >>>> The result might differ in absolute value and in sign, i.e. you can't even >>>> determine whether LAB1 or LAB2 comes first in the generated code as the >>>> order of stubs might differ from the order of respective labels. >>> >>> So, I think this all doesn't matter any. Every address gs(LAB) fits in >>> 16-bits by definition, and every gs(LAB1) - gs(LAB2) fits into 16 bits and >> >> Yes, you are right. Label differences could be implemented. AFAIK there is currently no activity by the Binutils folks to add respective support, so it is somewhat pointless to add that support to avr-gcc... > > > [ pause, built an avr compiler ] So, I checked code-gen for gcc.c-torture/compile/labels-2.c and it looked fine: > > ldi r24,lo8(gs(.L2)) > ldi r25,hi8(gs(.L2)) > std Y+2,r25 > std Y+1,r24 > ldi r18,lo8(gs(.L3)) > ldi r19,hi8(gs(.L3)) > ldi r24,lo8(gs(.L4)) > ldi r25,hi8(gs(.L4)) > mov r20,r18 > mov r21,r19 > sub r20,r24 > > So, apparently quite a lot of the code-gen is already wired up. Since this generated code, I wasn't sure what error you're trying to hide? I tried all the test cases your mentioned, none failed to produce code or failed to assemble that code with -mmcu=atmega2560 nor any other cpu I could find, so, trivially, I must not quite understand what doesn't work yet. > > I did notice that gcc.c-torture/execute/pr70460.c produced: > > .word .L3-(.L2) > > which seems wrong, given all the other code-gen. I think this has to be gs(.L3)-(gs(.L2)), no? I tried to get binutils to do that for me directly with a .word and it seemed resistant; which is unfortunate. Well, the GCC specification on void* arithmetic requires that void is handled as if it has a size of one, and .L3-.L2 meets that requirement. As code addresses on avr are word addresses, not byte addresses, the above code will crash. A working expression would be (.L3-.L2)/2 but 1) this conflicts with the gcc specification 2) it does not work with stubs 3) the linker does not handle this correctly if relaxation is on. All the label-arithmetic test cases in GCC testsuite don't actually need stub generation because the binaries are not big enough. Using gs, the expression would be gs(.L3)-(gs(.L2)) as gs implements word addresses, not byte addresses. This also means the problem is not only present with 3-byte PC devises but also for smaller ones. > > If you consider the above to be a code-gen bug, then you can do something like: > > Index: config/avr/avr.c > =================================================================== > --- config/avr/avr.c (revision 241837) > +++ config/avr/avr.c (working copy) > @@ -9422,6 +9422,21 @@ > x = plus_constant (Pmode, x, AVR_TINY_PM_OFFSET); > } > > + /* We generate stubs using gs(), but binutils doesn't support that > + here. */ > + if (AVR_3_BYTE_PC > + && GET_CODE (x) == MINUS > + && GET_CODE (XEXP (x, 0)) == LABEL_REF > + && GET_CODE (XEXP (x, 1)) == LABEL_REF) > + return false; > + if (AVR_3_BYTE_PC > + && GET_CODE (x) == MINUS > + && GET_CODE (XEXP (x, 0)) == SUBREG > + && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF > + && GET_CODE (XEXP (x, 1)) == SUBREG > + && GET_CODE (XEXP (XEXP (x, 1), 0)) == LABEL_REF) > + return false; > + > return default_assemble_integer (x, size, aligned_p); > } > > to get the compiler to error out to prevent bad code-gen that binutils can't handle. If you want, you can also declare by fiat that subtraction might be performed on the stub or the actual function, and so any code that does this isn't supported (runtime unspecified behavior), and then you just mark the execute testcase as bad (not supportable on avr, since avr blew the binutils support for gs). The compile only test cases work fine now, so nothing needs to be done for them. ICE is not a nice approach, IMO. I'd prefer some more graceful error using code locations of the labels (which are not available). > > If you go for the above and make it a hard error, then a patch in the style of the original patch would be fine, but please just mark the ones that fail and please key of avr*, as this is an avr-only misfeature. If avr did it right, they would complete gs() support so that gs(LAB)-gs(LAB) works. gcc has a fetish for + and - working with labels and constants. > > The completely different solution would be to never use gs(), and generate code that is 3 byte aware, but, I suspect you're unlikely to want to do that. That's the worst solution of all because it changes the ABI, leads to code bloat, and many more issues. And just reduce testsuite fallout for some crazy tests? Really?
On Nov 4, 2016, at 2:35 AM, Georg-Johann Lay <avr@gjlay.de> wrote: > >> .word .L3-(.L2) >> >> which seems wrong, given all the other code-gen. I think this has to be gs(.L3)-(gs(.L2)), no? I tried to get binutils to do that for me directly with a .word and it seemed resistant; which is unfortunate. > Using gs, the expression would be gs(.L3)-(gs(.L2)) as gs implements word addresses, not byte addresses. As I said, I tried that and could not get it to work. >> The compile only test cases work fine now, so nothing needs to be done for them. > > ICE is not a nice approach I never saw an ICE with current release binutils and top of tree gcc. If you want me to see an ICE and comment on it, I would need the command line apparently. > , IMO. I'd prefer some more graceful error using code locations of the labels (which are not available). My preference is code-gen. :-) Anyway, the change I posted creates nice graceful errors, if one wants.
Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 241837) +++ config/avr/avr.c (working copy) @@ -9422,6 +9422,21 @@ x = plus_constant (Pmode, x, AVR_TINY_PM_OFFSET); } + /* We generate stubs using gs(), but binutils doesn't support that + here. */ + if (AVR_3_BYTE_PC + && GET_CODE (x) == MINUS + && GET_CODE (XEXP (x, 0)) == LABEL_REF + && GET_CODE (XEXP (x, 1)) == LABEL_REF) + return false; + if (AVR_3_BYTE_PC + && GET_CODE (x) == MINUS + && GET_CODE (XEXP (x, 0)) == SUBREG + && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF + && GET_CODE (XEXP (x, 1)) == SUBREG + && GET_CODE (XEXP (XEXP (x, 1), 0)) == LABEL_REF) + return false; + return default_assemble_integer (x, size, aligned_p); }