1 //===- bolt/Core/BinaryBasicBlock.cpp - Low-level basic block -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the BinaryBasicBlock class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "bolt/Core/BinaryBasicBlock.h"
14 #include "bolt/Core/BinaryContext.h"
15 #include "bolt/Core/BinaryFunction.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/MC/MCAsmLayout.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/Support/Errc.h"
20
21 #define DEBUG_TYPE "bolt"
22
23 namespace llvm {
24 namespace bolt {
25
26 constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET;
27
operator <(const BinaryBasicBlock & LHS,const BinaryBasicBlock & RHS)28 bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
29 return LHS.Index < RHS.Index;
30 }
31
hasCFG() const32 bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); }
33
isEntryPoint() const34 bool BinaryBasicBlock::isEntryPoint() const {
35 return getParent()->isEntryPoint(*this);
36 }
37
hasInstructions() const38 bool BinaryBasicBlock::hasInstructions() const {
39 return getParent()->hasInstructions();
40 }
41
getJumpTable() const42 const JumpTable *BinaryBasicBlock::getJumpTable() const {
43 const MCInst *Inst = getLastNonPseudoInstr();
44 const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
45 return JT;
46 }
47
adjustNumPseudos(const MCInst & Inst,int Sign)48 void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
49 BinaryContext &BC = Function->getBinaryContext();
50 if (BC.MIB->isPseudo(Inst))
51 NumPseudos += Sign;
52 }
53
getFirstNonPseudo()54 BinaryBasicBlock::iterator BinaryBasicBlock::getFirstNonPseudo() {
55 const BinaryContext &BC = Function->getBinaryContext();
56 for (auto II = Instructions.begin(), E = Instructions.end(); II != E; ++II) {
57 if (!BC.MIB->isPseudo(*II))
58 return II;
59 }
60 return end();
61 }
62
getLastNonPseudo()63 BinaryBasicBlock::reverse_iterator BinaryBasicBlock::getLastNonPseudo() {
64 const BinaryContext &BC = Function->getBinaryContext();
65 for (auto RII = Instructions.rbegin(), E = Instructions.rend(); RII != E;
66 ++RII) {
67 if (!BC.MIB->isPseudo(*RII))
68 return RII;
69 }
70 return rend();
71 }
72
validateSuccessorInvariants()73 bool BinaryBasicBlock::validateSuccessorInvariants() {
74 const MCInst *Inst = getLastNonPseudoInstr();
75 const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
76 BinaryContext &BC = Function->getBinaryContext();
77 bool Valid = true;
78
79 if (JT) {
80 // Note: for now we assume that successors do not reference labels from
81 // any overlapping jump tables. We only look at the entries for the jump
82 // table that is referenced at the last instruction.
83 const auto Range = JT->getEntriesForAddress(BC.MIB->getJumpTable(*Inst));
84 const std::vector<const MCSymbol *> Entries(
85 std::next(JT->Entries.begin(), Range.first),
86 std::next(JT->Entries.begin(), Range.second));
87 std::set<const MCSymbol *> UniqueSyms(Entries.begin(), Entries.end());
88 for (BinaryBasicBlock *Succ : Successors) {
89 auto Itr = UniqueSyms.find(Succ->getLabel());
90 if (Itr != UniqueSyms.end()) {
91 UniqueSyms.erase(Itr);
92 } else {
93 // Work on the assumption that jump table blocks don't
94 // have a conditional successor.
95 Valid = false;
96 errs() << "BOLT-WARNING: Jump table successor " << Succ->getName()
97 << " not contained in the jump table.\n";
98 }
99 }
100 // If there are any leftover entries in the jump table, they
101 // must be one of the function end labels.
102 if (Valid) {
103 for (const MCSymbol *Sym : UniqueSyms) {
104 Valid &= (Sym == Function->getFunctionEndLabel() ||
105 Sym == Function->getFunctionColdEndLabel());
106 if (!Valid) {
107 errs() << "BOLT-WARNING: Jump table contains illegal entry: "
108 << Sym->getName() << "\n";
109 }
110 }
111 }
112 } else {
113 // Unknown control flow.
114 if (Inst && BC.MIB->isIndirectBranch(*Inst))
115 return true;
116
117 const MCSymbol *TBB = nullptr;
118 const MCSymbol *FBB = nullptr;
119 MCInst *CondBranch = nullptr;
120 MCInst *UncondBranch = nullptr;
121
122 if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
123 switch (Successors.size()) {
124 case 0:
125 Valid = !CondBranch && !UncondBranch;
126 break;
127 case 1: {
128 const bool HasCondBlock =
129 CondBranch && Function->getBasicBlockForLabel(
130 BC.MIB->getTargetSymbol(*CondBranch));
131 Valid = !CondBranch || !HasCondBlock;
132 break;
133 }
134 case 2:
135 Valid = (CondBranch &&
136 (TBB == getConditionalSuccessor(true)->getLabel() &&
137 ((!UncondBranch && !FBB) ||
138 (UncondBranch &&
139 FBB == getConditionalSuccessor(false)->getLabel()))));
140 break;
141 }
142 }
143 }
144 if (!Valid) {
145 errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
146 << getName() << "\n";
147 if (JT) {
148 errs() << "Jump Table instruction addr = 0x"
149 << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
150 JT->print(errs());
151 }
152 getFunction()->dump();
153 }
154 return Valid;
155 }
156
getSuccessor(const MCSymbol * Label) const157 BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
158 if (!Label && succ_size() == 1)
159 return *succ_begin();
160
161 for (BinaryBasicBlock *BB : successors())
162 if (BB->getLabel() == Label)
163 return BB;
164
165 return nullptr;
166 }
167
getSuccessor(const MCSymbol * Label,BinaryBranchInfo & BI) const168 BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label,
169 BinaryBranchInfo &BI) const {
170 auto BIIter = branch_info_begin();
171 for (BinaryBasicBlock *BB : successors()) {
172 if (BB->getLabel() == Label) {
173 BI = *BIIter;
174 return BB;
175 }
176 ++BIIter;
177 }
178
179 return nullptr;
180 }
181
getLandingPad(const MCSymbol * Label) const182 BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
183 for (BinaryBasicBlock *BB : landing_pads())
184 if (BB->getLabel() == Label)
185 return BB;
186
187 return nullptr;
188 }
189
getCFIStateAtInstr(const MCInst * Instr) const190 int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const {
191 assert(
192 getFunction()->getState() >= BinaryFunction::State::CFG &&
193 "can only calculate CFI state when function is in or past the CFG state");
194
195 const BinaryFunction::CFIInstrMapType &FDEProgram =
196 getFunction()->getFDEProgram();
197
198 // Find the last CFI preceding Instr in this basic block.
199 const MCInst *LastCFI = nullptr;
200 bool InstrSeen = (Instr == nullptr);
201 for (auto RII = Instructions.rbegin(), E = Instructions.rend(); RII != E;
202 ++RII) {
203 if (!InstrSeen) {
204 InstrSeen = (&*RII == Instr);
205 continue;
206 }
207 if (Function->getBinaryContext().MIB->isCFI(*RII)) {
208 LastCFI = &*RII;
209 break;
210 }
211 }
212
213 assert(InstrSeen && "instruction expected in basic block");
214
215 // CFI state is the same as at basic block entry point.
216 if (!LastCFI)
217 return getCFIState();
218
219 // Fold all RememberState/RestoreState sequences, such as for:
220 //
221 // [ CFI #(K-1) ]
222 // RememberState (#K)
223 // ....
224 // RestoreState
225 // RememberState
226 // ....
227 // RestoreState
228 // [ GNU_args_size ]
229 // RememberState
230 // ....
231 // RestoreState <- LastCFI
232 //
233 // we return K - the most efficient state to (re-)generate.
234 int64_t State = LastCFI->getOperand(0).getImm();
235 while (State >= 0 &&
236 FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) {
237 int32_t Depth = 1;
238 --State;
239 assert(State >= 0 && "first CFI cannot be RestoreState");
240 while (Depth && State >= 0) {
241 const MCCFIInstruction &CFIInstr = FDEProgram[State];
242 if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState)
243 ++Depth;
244 else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState)
245 --Depth;
246 --State;
247 }
248 assert(Depth == 0 && "unbalanced RememberState/RestoreState stack");
249
250 // Skip any GNU_args_size.
251 while (State >= 0 && FDEProgram[State].getOperation() ==
252 MCCFIInstruction::OpGnuArgsSize) {
253 --State;
254 }
255 }
256
257 assert((State + 1 >= 0) && "miscalculated CFI state");
258 return State + 1;
259 }
260
addSuccessor(BinaryBasicBlock * Succ,uint64_t Count,uint64_t MispredictedCount)261 void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ, uint64_t Count,
262 uint64_t MispredictedCount) {
263 Successors.push_back(Succ);
264 BranchInfo.push_back({Count, MispredictedCount});
265 Succ->Predecessors.push_back(this);
266 }
267
replaceSuccessor(BinaryBasicBlock * Succ,BinaryBasicBlock * NewSucc,uint64_t Count,uint64_t MispredictedCount)268 void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ,
269 BinaryBasicBlock *NewSucc,
270 uint64_t Count,
271 uint64_t MispredictedCount) {
272 Succ->removePredecessor(this, /*Multiple=*/false);
273 auto I = succ_begin();
274 auto BI = BranchInfo.begin();
275 for (; I != succ_end(); ++I) {
276 assert(BI != BranchInfo.end() && "missing BranchInfo entry");
277 if (*I == Succ)
278 break;
279 ++BI;
280 }
281 assert(I != succ_end() && "no such successor!");
282
283 *I = NewSucc;
284 *BI = BinaryBranchInfo{Count, MispredictedCount};
285 NewSucc->addPredecessor(this);
286 }
287
removeAllSuccessors()288 void BinaryBasicBlock::removeAllSuccessors() {
289 SmallPtrSet<BinaryBasicBlock *, 2> UniqSuccessors(succ_begin(), succ_end());
290 for (BinaryBasicBlock *SuccessorBB : UniqSuccessors)
291 SuccessorBB->removePredecessor(this);
292 Successors.clear();
293 BranchInfo.clear();
294 }
295
removeSuccessor(BinaryBasicBlock * Succ)296 void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) {
297 Succ->removePredecessor(this, /*Multiple=*/false);
298 auto I = succ_begin();
299 auto BI = BranchInfo.begin();
300 for (; I != succ_end(); ++I) {
301 assert(BI != BranchInfo.end() && "missing BranchInfo entry");
302 if (*I == Succ)
303 break;
304 ++BI;
305 }
306 assert(I != succ_end() && "no such successor!");
307
308 Successors.erase(I);
309 BranchInfo.erase(BI);
310 }
311
addPredecessor(BinaryBasicBlock * Pred)312 void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
313 Predecessors.push_back(Pred);
314 }
315
removePredecessor(BinaryBasicBlock * Pred,bool Multiple)316 void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred,
317 bool Multiple) {
318 // Note: the predecessor could be listed multiple times.
319 bool Erased = false;
320 for (auto PredI = Predecessors.begin(); PredI != Predecessors.end();) {
321 if (*PredI == Pred) {
322 Erased = true;
323 PredI = Predecessors.erase(PredI);
324 if (!Multiple)
325 return;
326 } else {
327 ++PredI;
328 }
329 }
330 assert(Erased && "Pred is not a predecessor of this block!");
331 (void)Erased;
332 }
333
removeDuplicateConditionalSuccessor(MCInst * CondBranch)334 void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) {
335 assert(succ_size() == 2 && Successors[0] == Successors[1] &&
336 "conditional successors expected");
337
338 BinaryBasicBlock *Succ = Successors[0];
339 const BinaryBranchInfo CondBI = BranchInfo[0];
340 const BinaryBranchInfo UncondBI = BranchInfo[1];
341
342 eraseInstruction(findInstruction(CondBranch));
343
344 Successors.clear();
345 BranchInfo.clear();
346
347 Successors.push_back(Succ);
348
349 uint64_t Count = COUNT_NO_PROFILE;
350 if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE)
351 Count = CondBI.Count + UncondBI.Count;
352 BranchInfo.push_back({Count, 0});
353 }
354
updateJumpTableSuccessors()355 void BinaryBasicBlock::updateJumpTableSuccessors() {
356 const JumpTable *JT = getJumpTable();
357 assert(JT && "Expected jump table instruction.");
358
359 // Clear existing successors.
360 removeAllSuccessors();
361
362 // Generate the list of successors in deterministic order without duplicates.
363 SmallVector<BinaryBasicBlock *, 16> SuccessorBBs;
364 for (const MCSymbol *Label : JT->Entries) {
365 BinaryBasicBlock *BB = getFunction()->getBasicBlockForLabel(Label);
366 // Ignore __builtin_unreachable()
367 if (!BB) {
368 assert(Label == getFunction()->getFunctionEndLabel() &&
369 "JT label should match a block or end of function.");
370 continue;
371 }
372 SuccessorBBs.emplace_back(BB);
373 }
374 llvm::sort(SuccessorBBs,
375 [](const BinaryBasicBlock *BB1, const BinaryBasicBlock *BB2) {
376 return BB1->getInputOffset() < BB2->getInputOffset();
377 });
378 SuccessorBBs.erase(std::unique(SuccessorBBs.begin(), SuccessorBBs.end()),
379 SuccessorBBs.end());
380
381 for (BinaryBasicBlock *BB : SuccessorBBs)
382 addSuccessor(BB);
383 }
384
adjustExecutionCount(double Ratio)385 void BinaryBasicBlock::adjustExecutionCount(double Ratio) {
386 auto adjustedCount = [&](uint64_t Count) -> uint64_t {
387 double NewCount = Count * Ratio;
388 if (!NewCount && Count && (Ratio > 0.0))
389 NewCount = 1;
390 return NewCount;
391 };
392
393 setExecutionCount(adjustedCount(getKnownExecutionCount()));
394 for (BinaryBranchInfo &BI : branch_info()) {
395 if (BI.Count != COUNT_NO_PROFILE)
396 BI.Count = adjustedCount(BI.Count);
397 if (BI.MispredictedCount != COUNT_INFERRED)
398 BI.MispredictedCount = adjustedCount(BI.MispredictedCount);
399 }
400 }
401
analyzeBranch(const MCSymbol * & TBB,const MCSymbol * & FBB,MCInst * & CondBranch,MCInst * & UncondBranch)402 bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB, const MCSymbol *&FBB,
403 MCInst *&CondBranch,
404 MCInst *&UncondBranch) {
405 auto &MIB = Function->getBinaryContext().MIB;
406 return MIB->analyzeBranch(Instructions.begin(), Instructions.end(), TBB, FBB,
407 CondBranch, UncondBranch);
408 }
409
isMacroOpFusionPair(const_iterator I) const410 bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const {
411 auto &MIB = Function->getBinaryContext().MIB;
412 ArrayRef<MCInst> Insts = Instructions;
413 return MIB->isMacroOpFusionPair(Insts.slice(I - begin()));
414 }
415
416 BinaryBasicBlock::const_iterator
getMacroOpFusionPair() const417 BinaryBasicBlock::getMacroOpFusionPair() const {
418 if (!Function->getBinaryContext().isX86())
419 return end();
420
421 if (getNumNonPseudos() < 2 || succ_size() != 2)
422 return end();
423
424 auto RI = getLastNonPseudo();
425 assert(RI != rend() && "cannot have an empty block with 2 successors");
426
427 BinaryContext &BC = Function->getBinaryContext();
428
429 // Skip instruction if it's an unconditional branch following
430 // a conditional one.
431 if (BC.MIB->isUnconditionalBranch(*RI))
432 ++RI;
433
434 if (!BC.MIB->isConditionalBranch(*RI))
435 return end();
436
437 // Start checking with instruction preceding the conditional branch.
438 ++RI;
439 if (RI == rend())
440 return end();
441
442 auto II = std::prev(RI.base()); // convert to a forward iterator
443 if (isMacroOpFusionPair(II))
444 return II;
445
446 return end();
447 }
448
getTerminatorBefore(MCInst * Pos)449 MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) {
450 BinaryContext &BC = Function->getBinaryContext();
451 auto Itr = rbegin();
452 bool Check = Pos ? false : true;
453 MCInst *FirstTerminator = nullptr;
454 while (Itr != rend()) {
455 if (!Check) {
456 if (&*Itr == Pos)
457 Check = true;
458 ++Itr;
459 continue;
460 }
461 if (BC.MIB->isTerminator(*Itr))
462 FirstTerminator = &*Itr;
463 ++Itr;
464 }
465 return FirstTerminator;
466 }
467
hasTerminatorAfter(MCInst * Pos)468 bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) {
469 BinaryContext &BC = Function->getBinaryContext();
470 auto Itr = rbegin();
471 while (Itr != rend()) {
472 if (&*Itr == Pos)
473 return false;
474 if (BC.MIB->isTerminator(*Itr))
475 return true;
476 ++Itr;
477 }
478 return false;
479 }
480
swapConditionalSuccessors()481 bool BinaryBasicBlock::swapConditionalSuccessors() {
482 if (succ_size() != 2)
483 return false;
484
485 std::swap(Successors[0], Successors[1]);
486 std::swap(BranchInfo[0], BranchInfo[1]);
487 return true;
488 }
489
addBranchInstruction(const BinaryBasicBlock * Successor)490 void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) {
491 assert(isSuccessor(Successor));
492 BinaryContext &BC = Function->getBinaryContext();
493 MCInst NewInst;
494 std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex);
495 BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
496 Instructions.emplace_back(std::move(NewInst));
497 }
498
addTailCallInstruction(const MCSymbol * Target)499 void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
500 BinaryContext &BC = Function->getBinaryContext();
501 MCInst NewInst;
502 BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get());
503 Instructions.emplace_back(std::move(NewInst));
504 }
505
getNumCalls() const506 uint32_t BinaryBasicBlock::getNumCalls() const {
507 uint32_t N = 0;
508 BinaryContext &BC = Function->getBinaryContext();
509 for (const MCInst &Instr : Instructions) {
510 if (BC.MIB->isCall(Instr))
511 ++N;
512 }
513 return N;
514 }
515
getNumPseudos() const516 uint32_t BinaryBasicBlock::getNumPseudos() const {
517 #ifndef NDEBUG
518 BinaryContext &BC = Function->getBinaryContext();
519 uint32_t N = 0;
520 for (const MCInst &Instr : Instructions)
521 if (BC.MIB->isPseudo(Instr))
522 ++N;
523
524 if (N != NumPseudos) {
525 errs() << "BOLT-ERROR: instructions for basic block " << getName()
526 << " in function " << *Function << ": calculated pseudos " << N
527 << ", set pseudos " << NumPseudos << ", size " << size() << '\n';
528 llvm_unreachable("pseudos mismatch");
529 }
530 #endif
531 return NumPseudos;
532 }
533
534 ErrorOr<std::pair<double, double>>
getBranchStats(const BinaryBasicBlock * Succ) const535 BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
536 if (Function->hasValidProfile()) {
537 uint64_t TotalCount = 0;
538 uint64_t TotalMispreds = 0;
539 for (const BinaryBranchInfo &BI : BranchInfo) {
540 if (BI.Count != COUNT_NO_PROFILE) {
541 TotalCount += BI.Count;
542 TotalMispreds += BI.MispredictedCount;
543 }
544 }
545
546 if (TotalCount > 0) {
547 auto Itr = llvm::find(Successors, Succ);
548 assert(Itr != Successors.end());
549 const BinaryBranchInfo &BI = BranchInfo[Itr - Successors.begin()];
550 if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
551 if (TotalMispreds == 0)
552 TotalMispreds = 1;
553 return std::make_pair(double(BI.Count) / TotalCount,
554 double(BI.MispredictedCount) / TotalMispreds);
555 }
556 }
557 }
558 return make_error_code(llvm::errc::result_out_of_range);
559 }
560
dump() const561 void BinaryBasicBlock::dump() const {
562 BinaryContext &BC = Function->getBinaryContext();
563 if (Label)
564 outs() << Label->getName() << ":\n";
565 BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
566 getOffset(), Function);
567 outs() << "preds:";
568 for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
569 outs() << " " << (*itr)->getName();
570 }
571 outs() << "\nsuccs:";
572 for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
573 outs() << " " << (*itr)->getName();
574 }
575 outs() << "\n";
576 }
577
estimateSize(const MCCodeEmitter * Emitter) const578 uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
579 return Function->getBinaryContext().computeCodeSize(begin(), end(), Emitter);
580 }
581
582 BinaryBasicBlock::BinaryBranchInfo &
getBranchInfo(const BinaryBasicBlock & Succ)583 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
584 auto BI = branch_info_begin();
585 for (BinaryBasicBlock *BB : successors()) {
586 if (&Succ == BB)
587 return *BI;
588 ++BI;
589 }
590
591 llvm_unreachable("Invalid successor");
592 return *BI;
593 }
594
595 BinaryBasicBlock::BinaryBranchInfo &
getBranchInfo(const MCSymbol * Label)596 BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) {
597 auto BI = branch_info_begin();
598 for (BinaryBasicBlock *BB : successors()) {
599 if (BB->getLabel() == Label)
600 return *BI;
601 ++BI;
602 }
603
604 llvm_unreachable("Invalid successor");
605 return *BI;
606 }
607
splitAt(iterator II)608 BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
609 assert(II != end() && "expected iterator pointing to instruction");
610
611 BinaryBasicBlock *NewBlock = getFunction()->addBasicBlock();
612
613 // Adjust successors/predecessors and propagate the execution count.
614 moveAllSuccessorsTo(NewBlock);
615 addSuccessor(NewBlock, getExecutionCount(), 0);
616
617 // Set correct CFI state for the new block.
618 NewBlock->setCFIState(getCFIStateAtInstr(&*II));
619
620 // Move instructions over.
621 adjustNumPseudos(II, end(), -1);
622 NewBlock->addInstructions(II, end());
623 Instructions.erase(II, end());
624
625 return NewBlock;
626 }
627
updateOutputValues(const MCAsmLayout & Layout)628 void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) {
629 if (!LocSyms)
630 return;
631
632 const uint64_t BBAddress = getOutputAddressRange().first;
633 const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel());
634 for (const auto &LocSymKV : *LocSyms) {
635 const uint32_t InputFunctionOffset = LocSymKV.first;
636 const uint32_t OutputOffset = static_cast<uint32_t>(
637 Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
638 getOffsetTranslationTable().emplace_back(
639 std::make_pair(OutputOffset, InputFunctionOffset));
640
641 // Update reverse (relative to BAT) address lookup table for function.
642 if (getFunction()->requiresAddressTranslation()) {
643 getFunction()->getInputOffsetToAddressMap().emplace(
644 std::make_pair(InputFunctionOffset, OutputOffset + BBAddress));
645 }
646 }
647 LocSyms.reset(nullptr);
648 }
649
650 } // namespace bolt
651 } // namespace llvm
652