New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[avr] Wrong code to indirect call functions located beyond the first 128KiB code segment. #58856
Comments
while Clang generates the following code:
The |
Ah, yes, that is another (separate) bug. I was testing with the atmega328p, which correctly generates |
Yes.
Yes. FYI, to factor this out in inline assembly, avr-gcc supports |
avr-gcc emits |
avr-gcc shows the relocation must emit void fun (int);
void (*pfun)(int) = fun;
void (*get_pfun (void))(int)
{
return fun;
}
For devices with 2-byte PC or when the label is in the 128 KiB code block covered by The difference is for devices with 3-byte PC and when the label outside the 128 KiB segment covered by
The bug has 2 parts:
An example where #ifdef __AVR_3_BYTE_PC__
ldi r16, hh8(pm(__vectors))
out _SFR_IO_ADDR(EIND), r16
#endif /* __AVR_3_BYTE_PC__ */ cf. The linker has similar magic to infer the value of See also |
There is probably a third bug: I don't think ld.lld currently supports trampoline functions. |
fixed by https://reviews.llvm.org/D142298. I will take a look at how to emit trampoline functions in lld. |
So to make this work we need 3 parts:
To extend on the opening comment #1, here is the code as generated by GNU:
On the other hand, if the application starts at, say, 0x20000 due to
But a stub is needed if, say, func is located in lower 128 KiB of code space. |
With my patch and your original test program (as below)
Build with command
I think all the 3 parts you mentioned become correct.
So I am sure all your concerns are fixed by my patch. |
|
We need not consider lld now, currently clang still calls avr-ld as default linker. |
fixed in 029f669 |
Fixes llvm/llvm-project#58856 Reviewed By: aykevl Differential Revision: https://reviews.llvm.org/D142298
Consider the following C code:
and compiled with:
So that the code mimics a function
func
located at 0x22222. There are problems with the generated code:icall
to executef()
, buticall
will always target the low 128KiB segment. The correct instruction iseicall
resp.eijmp
for tail-calls.pm_lo8(sym)
andpm_hi8(sym)
, where the correct code will uselo8(gs(sym))
andhi8(gs(sym))
; so the GNU linker will generate stubs as needed. Correct RELOCs areR_AVR_LO8_LDI_GS
resp.R_AVR_HI8_LDI_GS
.icall
/ijmp
won't work either, correct areeicall
/eijmp
, cf. also startup-code.FYI, the disassembly of main is as of
foo.lst
is:so the call will target 0x2222, not 0x22222.
The text was updated successfully, but these errors were encountered: