Lines Matching +full:- +full:- +full:branch

1 //===- ConcatOutputSection.cpp --------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
29 assert(input->parent == this); in addInput()
31 align = input->align; in addInput()
32 flags = input->getFlags(); in addInput()
34 align = std::max(align, input->align); in addInput()
40 // Branch-range extension can be implemented in two ways, either through ...
42 // (1) Branch islands: Single branch instructions (also of limited range),
44 // destination. On ARM64, as 16 branch islands are needed to hop between
45 // opposite ends of a 2 GiB program. LD64 uses branch islands exclusively,
49 // register, followed by a register-indirect branch. Thunks are
57 // implement thunks. TODO: Adding support for branch islands!
59 // Internally -- as expressed in LLD's data structures -- a
60 // branch-range-extension thunk consists of:
65 // (3.1) new data for the instructions to load & branch to the far address +
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
111 // is placed, it and all previous input-section addresses are final.
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
122 // thunks for programs so large that branch source & destination addresses
123 // might differ more than the range of branch instruction(s).
125 if (!target->usesThunks()) in needsThunks()
129 isecAddr = alignToPowerOf2(isecAddr, isec->align) + isec->getSize(); in needsThunks()
130 if (isecAddr - addr + in.stubs->getSize() <= in needsThunks()
131 std::min(target->backwardBranchRange, target->forwardBranchRange)) in needsThunks()
135 for (Reloc &r : isec->relocs) { in needsThunks()
136 if (!target->hasAttr(r.type, RelocAttrBits::BRANCH)) in needsThunks()
139 // Pre-populate the thunkMap and memoize call site counts for every in needsThunks()
147 // We can avoid work on InputSections that have no BRANCH relocs. in needsThunks()
148 isec->hasCallSites = true; in needsThunks()
155 // beyond which stubs are within range of a simple forward branch.
164 // currently-active section get finalized, and all input sections are in estimateStubsInRangeVA()
171 uint64_t isecVA = inputs[callIdx]->getVA(); in estimateStubsInRangeVA()
175 isecEnd = alignToPowerOf2(isecEnd, isec->align) + isec->getSize(); in estimateStubsInRangeVA()
179 uint64_t forwardBranchRange = target->forwardBranchRange; in estimateStubsInRangeVA()
182 assert(isecEnd - isecVA <= forwardBranchRange && in estimateStubsInRangeVA()
184 uint64_t stubsInRangeVA = isecEnd + maxPotentialThunks * target->thunkSize + in estimateStubsInRangeVA()
185 in.stubs->getSize() - forwardBranchRange; in estimateStubsInRangeVA()
188 ", stubs = " + std::to_string(in.stubs->getSize()) + ", isecVA = " + in estimateStubsInRangeVA()
191 ", tail = " + utohexstr(isecEnd - isecVA) + in estimateStubsInRangeVA()
192 ", slop = " + utohexstr(forwardBranchRange - (isecEnd - isecVA))); in estimateStubsInRangeVA()
197 size = alignToPowerOf2(size, isec->align); in finalizeOne()
198 fileSize = alignToPowerOf2(fileSize, isec->align); in finalizeOne()
199 isec->outSecOff = size; in finalizeOne()
200 isec->isFinal = true; in finalizeOne()
201 size += isec->getSize(); in finalizeOne()
202 fileSize += isec->getFileSize(); in finalizeOne()
217 uint64_t forwardBranchRange = target->forwardBranchRange; in finalize()
218 uint64_t backwardBranchRange = target->backwardBranchRange; in finalize()
220 size_t thunkSize = target->thunkSize; in finalize()
229 // addr + size is the start address of the first non-finalized section. in finalize()
231 // inputs[finalIdx] is for finalization (address-assignment) in finalize()
233 // Kick-off by ensuring that the first input section has an address in finalize()
239 assert(isec->isFinal); in finalize()
240 uint64_t isecVA = isec->getVA(); in finalize()
242 // Assign addresses up-to the forward branch-range limit. in finalize()
245 // (on Arm64: 12). If a section starts with a branch instruction and in finalize()
246 // contains several branch instructions in succession, then the distance in finalize()
252 alignToPowerOf2(addr + size, inputs[finalIdx]->align) + in finalize()
253 inputs[finalIdx]->getSize(); in finalize()
254 if (expectedNewSize >= isecVA + forwardBranchRange - slop) in finalize()
259 if (!isec->hasCallSites) in finalize()
266 // reach any stub with a forward branch. Note that although it in finalize()
270 // (and start of __stubs) comes within range of a forward branch. in finalize()
274 std::vector<Reloc> &relocs = isec->relocs; in finalize()
276 // `-r` mode. in finalize()
281 if (!target->hasAttr(r.type, RelocAttrBits::BRANCH)) in finalize()
284 // Calculate branch reachability boundaries in finalize()
287 backwardBranchRange < callVA ? callVA - backwardBranchRange : 0; in finalize()
293 if (funcSym->isInStubs() && callVA >= stubsInRangeVA) { in finalize()
296 // are now within range of a simple forward branch. in finalize()
299 uint64_t funcVA = funcSym->resolveBranchVA(); in finalize()
309 uint64_t thunkVA = thunkInfo.isec->getVA(); in finalize()
317 // There were too many consecutive branch instructions for `slop` in finalize()
324 makeSyntheticInputSection(isec->getSegName(), isec->getName()); in finalize()
325 thunkInfo.isec->parent = this; in finalize()
326 assert(thunkInfo.isec->live); in finalize()
328 StringRef thunkName = saver().save(funcSym->getName() + ".thunk." + in finalize()
330 if (!isa<Defined>(funcSym) || cast<Defined>(funcSym)->isExternal()) { in finalize()
331 r.referent = thunkInfo.sym = symtab->addDefined( in finalize()
343 thunkInfo.sym->used = true; in finalize()
344 target->populateThunk(thunkInfo.isec, funcSym); in finalize()
351 log("thunks for " + parent->name + "," + name + in finalize()
361 isec->writeTo(buf + isec->outSecOff); in writeTo()
369 while (i < ie && (t == te || inputs[i]->empty() || in writeTo()
370 inputs[i]->outSecOff < thunks[t]->outSecOff)) { in writeTo()
371 inputs[i]->writeTo(buf + inputs[i]->outSecOff); in writeTo()
374 while (t < te && (i == ie || thunks[t]->outSecOff < inputs[i]->outSecOff)) { in writeTo()
375 thunks[t]->writeTo(buf + thunks[t]->outSecOff); in writeTo()
382 switch (sectionType(input->getFlags())) { in finalizeFlags()
383 default /*type-unspec'ed*/: in finalizeFlags()
400 flags |= input->getFlags(); in finalizeFlags()
407 NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()}); in getOrCreateForInput()
410 if (isec->getSegName() == segment_names::text && in getOrCreateForInput()
411 isec->getName() != section_names::gccExceptTab && in getOrCreateForInput()
412 isec->getName() != section_names::ehFrame) in getOrCreateForInput()
421 auto newNames = config->sectionRenameMap.find(key); in maybeRenameSection()
422 if (newNames != config->sectionRenameMap.end()) in maybeRenameSection()
423 return newNames->second; in maybeRenameSection()