<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Oct 20, 2015 at 5:36 PM, Sean Silva <span dir="ltr"><<a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Oct 20, 2015 at 4:56 PM, Hal Finkel via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Rui, Rafael, et al.,<br>
<br>
In order to move PPC64 support in lld to a point where it can self host, we need to deal with the following problem:<br>
<br>
On PPC, a relative branch can only have a signed 24-bit displacement (which is really a 26-bit signed displacement, once the two assumed lower-order bits are tacked on). Thus, the range is limited to +/- a few (tens of) megabytes, and if there is more code than that, we need to make other arrangements.<br>
<br>
As I understand it, other architectures (AArch64, for example), have similar limitations.<br>
<br>
Existing linkers handle this situation by inserting branch stubs, and placing the branch stubs close enough to the call sites.<br>
<br>
Here's a quick example:<br>
<br>
$ cat main.c<br>
void foo();<br>
int main() {<br>
  foo();<br>
  asm(".fill 50000000, 4, 0x60000000"); // lots of nops<br>
  return 0;<br>
}<br>
<br>
$ cat foo.c<br>
void foo() {}<br>
<br>
$ gcc -o btest main.c foo.c<br>
<br>
Now running objdump -d btest shows this relevant bit:<br>
<br>
0000000010000500 <0000003a.plt_branch.foo+0>:<br>
    10000500:   3d 82 ff ff     addis   r12,r2,-1<br>
    10000504:   e9 6c 7f e8     ld      r11,32744(r12)<br>
    10000508:   7d 69 03 a6     mtctr   r11<br>
    1000050c:   4e 80 04 20     bctr<br>
<br>
0000000010000510 <.main>:<br>
    10000510:   7c 08 02 a6     mflr    r0<br>
    10000514:   f8 01 00 10     std     r0,16(r1)<br>
    10000518:   fb e1 ff f8     std     r31,-8(r1)<br>
    1000051c:   f8 21 ff 81     stdu    r1,-128(r1)<br>
    10000520:   7c 3f 0b 78     mr      r31,r1<br>
    10000524:   4b ff ff dd     bl      10000500 <0000003a.plt_branch.foo+0><br>
    10000528:   60 00 00 00     nop<br>
    1000052c:   60 00 00 00     nop<br>
    10000530:   60 00 00 00     nop<br>
    10000534:   60 00 00 00     nop<br>
...<br>
<br>
So it has taken the actual call target address and stuck it in a data section (referenced from the TOC base pointer), and the stub loads the address and jumps there.<br>
<br>
Currently, lld seems to write each input section that is part of an output section, in order, consecutively into that output section. Dealing properly with long-branch stubs, however, seems to require inserting intervening stub segments in between other .text sections.  This affects not only direct calls, but calls into .plt too (since they too need to be in range), or we need to split (and, perhaps, duplicate .plt entries) in order to make sure they're close enough as well.<br>
<br>
One possible way to do this is:<br>
<br>
 if (total size < some threshold) {<br>
   everything will fit, so do what we do now<br>
 } else {<br>
   group the input text segments so that each group (including the size of stubs) is below the threshold (we can scan each segment for branch relocations to determine if stubs are necessary)<br>
   insert the necessary stub segments after each grouping<br>
 }<br>
<br>
Various heuristics can make the groupings chosen more or less optimal, but perhaps that's another matter.<br>
<br>
Thoughts?<br></blockquote><div><br></div></div></div><div>Could we have an OutputSection subclass whose finalize() method does this computation and edits its `std::vector<InputSection<ELFT> *> Sections` by inserting "phony" input sections and rewriting relocations? That way, the core layout algorithm is unaffected.</div></div></div></div></blockquote><div><br></div><div>That algorithm is sub-optimal because inter-group calls are always through stubs, even if call destination is pretty close in memory, no?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div><div>-- Sean Silva</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Thanks again,<br>
Hal<br>
<span><font color="#888888"><span class=""><br>
--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br></span>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</font></span></blockquote></div><br></div></div>
</blockquote></div><br></div></div>