Pymake's clinetoargv is very specific to pymake's use case, yet has been abused
as a replacement for shlex because shlex doesn't handle things properly for our
use cases.
Using pymake's clinetoargv, however, has shortcomings, and we're better off
importing its code in mozbuild, simplifying it a little, and using that
instead.
Plus, less dependencies on pymake will help kill it for good some day.
Add a branch range argument to LinkAndGetOffsetTo(): ARM64 branches
can't encode arbitrary ranges, so the linked list of unbound label uses
needs some consideration. We can't assume that a newly assembled branch
instruction will be able to point backwards to label->offset().
Change LinkAndGetOffsetTo() to a normal function instead of a template.
We don't need the code duplication just to apply different scale
factors. Throw the premature microoptimizers a bone by replacing the
element_size template argument with its logarithm.
Implement Assembler::PatchShortRangeBranchToVeneer() to insert the
veneer branch after the original short-range branch in the linked list
of uses of the unbound label.
Fix Assembler::bind() to understand that not all branches can reach the
label. Verify that these branches jump to a veneer instead.
Register short-range branches in LinkAndGetOffsetTo(), and unregister
them again in Assembler::bind().
Instead of storing byte offsets in the branch instructions using a
label, store instruction offsets, just like the finished branches do.
Use a 0 pc offset to terminate the linked list instead of -1.
This increases the maximum distance between linked branches to be the
same as the range of the branch instrructions. Previously, the
supported range was only 1/4 of what the branch instructions can
encode.
Provide protected functions for manipulating the linked list in
MozBaseAssembler, and rewrite Assembler::bind() and retarget() to use
them instead of decoding branches manually.
Move the LinkAndGet*OffsetTo functions into MozBaseAssembler. Our
version of these functions is completely different from the VIXL
versions.
We already have an ARM64 ImmBranchType which classifies the branch
instructions in the ISA. The /range/ classification is required because
we need unique small integers to pass to
AssemblerBufferWithConstantPool::registerBranchDeadline(). The b.cond
and cbz instructions have the same range, but different branch types.
Classify the 32 KB and 1 MB range branches as 'short-range'. Request
these branch ranges to be tracked by the new
AssemblerBufferWithConstantPools::NumShortBranchRanges faclity.
Also add two functions for computing the maximum forward and backward
reach of branches given their range enumerator.
This is the second part of the short branch handling in
AssemblerBufferWithConstantPools. The PatchShortRangeBranchToVeneer()
callback is called from finishPool() to patch short-range branches that
are about to expire.
Implement no-op versions of the callback for ARM and ARM64. These
versions will never be called as long as no short-line branches are
registered. They only exist to prevent linker errors in unoptimized
builds. In an optimized build, the unused function calls will be
optimized out because DeadlineSet<0>::empty() is hardwired to return
true.
Test the existing functionality of AssemblerBufferWithConstantPools
using a fake ISA that is much more constrained than ARM and ARM64.
Documant the Assembler callback that are required to use
AssemblerBufferWithConstantPools, and implement mock versions for the
unit test.
AssemblerBufferWithConstantPools geta a branchDeadlines_ member which keeps
track of forward branch to unbound labels.
Add a hasSpaceForInsts() method which collects the logic for checking for
available space in one place. Insert a constant pool both when constant pool
loads are about to go out of range, and when short-range branch deadlines are
about to expire.
Add registerBranchDeadline() and unregisterBranchDeadline() methods that the
assembler will use to add and remove branches to be tracked.