Skip to content

[lld-macho] Fix branch extension thunk estimation logic #120529

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

Merged
merged 6 commits into from
Jan 9, 2025
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions lld/MachO/ConcatOutputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,42 @@ uint64_t TextOutputSection::estimateStubsInRangeVA(size_t callIdx) const {
InputSection *isec = inputs[i];
isecEnd = alignToPowerOf2(isecEnd, isec->align) + isec->getSize();
}

// Tally up any thunks that have already been placed that have address higher
// than the equivalent callIdx. We first find the index of the first thunk
// that is beyond the current inputs[callIdx].
auto itPostcallIdxThunks = std::partition_point(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use llvm::partition_point()

Copy link
Contributor Author

@alx32 alx32 Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean another form or it ? We're already using partition_point.

EDIT: I see ... std=>llvm

thunks.begin(), thunks.end(),
[isecVA](const ConcatInputSection *t) { return t->getVA() <= isecVA; });
uint64_t existingForwardThunks = thunks.end() - itPostcallIdxThunks;

// Estimate the address after which call sites can safely call stubs
// directly rather than through intermediary thunks.
uint64_t forwardBranchRange = target->forwardBranchRange;
assert(isecEnd > forwardBranchRange &&
"should not run thunk insertion if all code fits in jump range");
assert(isecEnd - isecVA <= forwardBranchRange &&
"should only finalize sections in jump range");
uint64_t stubsInRangeVA = isecEnd + maxPotentialThunks * target->thunkSize +
in.stubs->getSize() - forwardBranchRange;

// Estimate the maximum size of the code, right before the stubs section.
uint64_t maxTextSize = 0;
// Add the size of all the inputs, including the unprocessed ones.
maxTextSize += isecEnd;

// Add the size of the thunks that may be created in the future. Since
// 'maxPotentialThunks' overcounts, this is an estimate of the upper limit.
maxTextSize += maxPotentialThunks * target->thunkSize;

// Add the size of the thunks that have already been created that are ahead
maxTextSize += existingForwardThunks * target->thunkSize;

// Estimated maximum VA of last stub.
uint64_t maxVAOfLastStub = maxTextSize + in.stubs->getSize();

// Calculaate the first address that is gueranteed to not need a thunk to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use (move) the original comment on Line 197 here.

// reach any stub.git
uint64_t stubsInRangeVA = maxVAOfLastStub - forwardBranchRange;

log("thunks = " + std::to_string(thunkMap.size()) +
", potential = " + std::to_string(maxPotentialThunks) +
", stubs = " + std::to_string(in.stubs->getSize()) + ", isecVA = " +
Expand Down
Loading