Lines Matching +full:all +full:- +full:inputs +full:- +full:2

1 //===- ConcatOutputSection.cpp --------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
29 assert(input->parent == this);
30 if (inputs.empty()) {
31 align = input->align;
32 flags = input->getFlags();
34 align = std::max(align, input->align);
37 inputs.push_back(input);
40 // Branch-range extension can be implemented in two ways, either through ...
45 // opposite ends of a 2 GiB program. LD64 uses branch islands exclusively,
48 // (2) Thunks: Instruction(s) to load the destination address into a scratch
49 // register, followed by a register-indirect branch. Thunks are
53 // program so that all call sites can have one within range.
59 // Internally -- as expressed in LLD's data structures -- a
60 // branch-range-extension thunk consists of:
64 // (2) new InputSection, which contains ...
70 // Nearly-optimal thunk-placement algorithm features:
74 // * Accounts for the exact space overhead of thunks - no heuristics
76 // * Exploits the full range of call instructions - forward & backward
85 // thunks are necessary to serve all call sites in a very large program. A
86 // thunkInfo stores state for all thunks associated with a particular
100 // to the inputs vector. We store new thunks via cheap vector append, rather
101 // than costly insertion into the inputs vector.
111 // is placed, it and all previous input-section addresses are final.
114 // the inputs and thunks vectors (both ordered by ascending address), which
119 // Determine whether we need thunks, which depends on the target arch -- RISC
120 // (i.e., ARM) generally does because it has limited-range branch/call
125 if (!target->usesThunks())
128 for (ConcatInputSection *isec : inputs)
129 isecAddr = alignToPowerOf2(isecAddr, isec->align) + isec->getSize();
130 if (isecAddr - addr + in.stubs->getSize() <=
131 std::min(target->backwardBranchRange, target->forwardBranchRange))
134 for (ConcatInputSection *isec : inputs) {
135 for (Reloc &r : isec->relocs) {
136 if (!target->hasAttr(r.type, RelocAttrBits::BRANCH))
139 // Pre-populate the thunkMap and memoize call site counts for every
148 isec->hasCallSites = true;
164 // currently-active section get finalized, and all input sections are
166 // jumps will need thunks, but we count all jumps.
171 uint64_t isecVA = inputs[callIdx]->getVA();
173 for (size_t i = callIdx; i < inputs.size(); i++) {
174 InputSection *isec = inputs[i];
175 isecEnd = alignToPowerOf2(isecEnd, isec->align) + isec->getSize();
179 uint64_t forwardBranchRange = target->forwardBranchRange;
181 "should not run thunk insertion if all code fits in jump range");
182 assert(isecEnd - isecVA <= forwardBranchRange &&
184 uint64_t stubsInRangeVA = isecEnd + maxPotentialThunks * target->thunkSize +
185 in.stubs->getSize() - forwardBranchRange;
188 ", stubs = " + std::to_string(in.stubs->getSize()) + ", isecVA = " +
191 ", tail = " + utohexstr(isecEnd - isecVA) +
192 ", slop = " + utohexstr(forwardBranchRange - (isecEnd - isecVA)));
197 size = alignToPowerOf2(size, isec->align);
198 fileSize = alignToPowerOf2(fileSize, isec->align);
199 isec->outSecOff = size;
200 isec->isFinal = true;
201 size += isec->getSize();
202 fileSize += isec->getFileSize();
206 for (ConcatInputSection *isec : inputs)
212 for (ConcatInputSection *isec : inputs)
217 uint64_t forwardBranchRange = target->forwardBranchRange;
218 uint64_t backwardBranchRange = target->backwardBranchRange;
220 size_t thunkSize = target->thunkSize;
226 // Walk all sections in order. Finalize all sections that are less than
229 // addr + size is the start address of the first non-finalized section.
231 // inputs[finalIdx] is for finalization (address-assignment)
233 // Kick-off by ensuring that the first input section has an address
234 for (size_t callIdx = 0, endIdx = inputs.size(); callIdx < endIdx;
237 finalizeOne(inputs[finalIdx++]);
238 ConcatInputSection *isec = inputs[callIdx];
239 assert(isec->isFinal);
240 uint64_t isecVA = isec->getVA();
242 // Assign addresses up-to the forward branch-range limit.
252 alignToPowerOf2(addr + size, inputs[finalIdx]->align) +
253 inputs[finalIdx]->getSize();
254 if (expectedNewSize >= isecVA + forwardBranchRange - slop)
256 finalizeOne(inputs[finalIdx++]);
259 if (!isec->hasCallSites)
263 // When we have finalized all input sections, __stubs (destined
274 std::vector<Reloc> &relocs = isec->relocs;
276 // `-r` mode.
281 if (!target->hasAttr(r.type, RelocAttrBits::BRANCH))
287 backwardBranchRange < callVA ? callVA - backwardBranchRange : 0;
293 if (funcSym->isInStubs() && callVA >= stubsInRangeVA) {
299 uint64_t funcVA = funcSym->resolveBranchVA();
309 uint64_t thunkVA = thunkInfo.isec->getVA();
324 makeSyntheticInputSection(isec->getSegName(), isec->getName());
325 thunkInfo.isec->parent = this;
326 assert(thunkInfo.isec->live);
328 StringRef thunkName = saver().save(funcSym->getName() + ".thunk." +
330 if (!isa<Defined>(funcSym) || cast<Defined>(funcSym)->isExternal()) {
331 r.referent = thunkInfo.sym = symtab->addDefined(
343 thunkInfo.sym->used = true;
344 target->populateThunk(thunkInfo.isec, funcSym);
351 log("thunks for " + parent->name + "," + name +
354 ", all calls = " + std::to_string(callSiteCount) +
360 for (ConcatInputSection *isec : inputs)
361 isec->writeTo(buf + isec->outSecOff);
366 size_t i = 0, ie = inputs.size();
369 while (i < ie && (t == te || inputs[i]->empty() ||
370 inputs[i]->outSecOff < thunks[t]->outSecOff)) {
371 inputs[i]->writeTo(buf + inputs[i]->outSecOff);
374 while (t < te && (i == ie || thunks[t]->outSecOff < inputs[i]->outSecOff)) {
375 thunks[t]->writeTo(buf + thunks[t]->outSecOff);
382 switch (sectionType(input->getFlags())) {
383 default /*type-unspec'ed*/:
400 flags |= input->getFlags();
407 NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()});
410 if (isec->getSegName() == segment_names::text &&
411 isec->getName() != section_names::gccExceptTab &&
412 isec->getName() != section_names::ehFrame)
421 auto newNames = config->sectionRenameMap.find(key);
422 if (newNames != config->sectionRenameMap.end())
423 return newNames->second;