[patch,testsuite] Support dg-require-effective-target label_offsets.

Georg-Johann Lay avr@gjlay.de
Thu Oct 27 10:16:00 GMT 2016


On 26.10.2016 18:51, Bernd Schmidt wrote:
> On 10/26/2016 04:46 PM, Georg-Johann Lay wrote:
>> +    if { [istarget avr-*-*] } {
>> +    # If the value of a label does not fit into 16 bits, the linker
>> +    # will generate a stub (containing a direct jump) and we end up
>> +    # with the address of the stub instead of the address of the very
>> +    # label.  Whereas it is legitimate to use such addresses for
>> +    # indirect jumps, it makes no sense to perform any arithmetic
>> +    # on such addresses.
>> +    return [check_no_compiler_messages label_offsets assembly {
>> +        #ifdef __AVR_3_BYTE_PC__
>> +        #error NO
>> +        #endif
>> +    }]
>> +    }
>> +    return 1;
>
> I'm not sure I understand the failure mode. Sure, you're not getting the
> address of the actual label, but the address of one that's equivalent - so why
> can't you do arithmetic on it? Where does it go wrong?

There are devices where the address of a label does not fit into 16 bits, which 
is a problem for indirect calls because not all of the program memory can be 
targeted by 16 bits.  The solution was to emit taking address of label LAB as 
gs(LAB) and let the linker resolve this ("gs" stands for "generate stub").

If LAB actually fits in 16 bits nothing special happens and we have LAB = gs(LAB).

If LAB doesn't fit then the linker generates a stub like:

gs_LAB:
    jump LAB

and resolves gs_LAB = gs(LAB).  gs_LAB must be located in the lower part of the 
program memory so that gs_LAB will fit into 16 bits.

An indirect call / jump then is 1) take address of LAB which returns gs_LAB and 
2) jump or call that address which jumps or calls gs_LAB which then jumps to LAB.

This works because absolute jumps and calls can target all of the program 
memory.  Moreover comparing gs() labels against each other or against 0 for 
(un)equality will also work as expected.

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.

> Am I right in thinking that only the execution test actually fails?
>
> Bernd

Some of the run tests are failing, but not all of them.  This is because gs() 
depends on code size and location.  But there are also some compile tests that 
fail as avr_print_operand_address tries to warn about such code with "pointer 
offset from symbol maybe incorrect".

Johann



More information about the Gcc-patches mailing list