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 28 bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) { 29 return LHS.Index < RHS.Index; 30 } 31 32 bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); } 33 34 bool BinaryBasicBlock::isEntryPoint() const { 35 return getParent()->isEntryPoint(*this); 36 } 37 38 bool BinaryBasicBlock::hasInstructions() const { 39 return getParent()->hasInstructions(); 40 } 41 42 const JumpTable *BinaryBasicBlock::getJumpTable() const { 43 const MCInst *Inst = getLastNonPseudoInstr(); 44 const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr; 45 return JT; 46 } 47 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 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 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 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->getFunctionEndLabel(getFragmentNum())); 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 157 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 168 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 182 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 190 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 (const MCInst &Inst : llvm::reverse(Instructions)) { 202 if (!InstrSeen) { 203 InstrSeen = (&Inst == Instr); 204 continue; 205 } 206 if (Function->getBinaryContext().MIB->isCFI(Inst)) { 207 LastCFI = &Inst; 208 break; 209 } 210 } 211 212 assert(InstrSeen && "instruction expected in basic block"); 213 214 // CFI state is the same as at basic block entry point. 215 if (!LastCFI) 216 return getCFIState(); 217 218 // Fold all RememberState/RestoreState sequences, such as for: 219 // 220 // [ CFI #(K-1) ] 221 // RememberState (#K) 222 // .... 223 // RestoreState 224 // RememberState 225 // .... 226 // RestoreState 227 // [ GNU_args_size ] 228 // RememberState 229 // .... 230 // RestoreState <- LastCFI 231 // 232 // we return K - the most efficient state to (re-)generate. 233 int64_t State = LastCFI->getOperand(0).getImm(); 234 while (State >= 0 && 235 FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) { 236 int32_t Depth = 1; 237 --State; 238 assert(State >= 0 && "first CFI cannot be RestoreState"); 239 while (Depth && State >= 0) { 240 const MCCFIInstruction &CFIInstr = FDEProgram[State]; 241 if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState) 242 ++Depth; 243 else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState) 244 --Depth; 245 --State; 246 } 247 assert(Depth == 0 && "unbalanced RememberState/RestoreState stack"); 248 249 // Skip any GNU_args_size. 250 while (State >= 0 && FDEProgram[State].getOperation() == 251 MCCFIInstruction::OpGnuArgsSize) { 252 --State; 253 } 254 } 255 256 assert((State + 1 >= 0) && "miscalculated CFI state"); 257 return State + 1; 258 } 259 260 void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ, uint64_t Count, 261 uint64_t MispredictedCount) { 262 Successors.push_back(Succ); 263 BranchInfo.push_back({Count, MispredictedCount}); 264 Succ->Predecessors.push_back(this); 265 } 266 267 void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ, 268 BinaryBasicBlock *NewSucc, 269 uint64_t Count, 270 uint64_t MispredictedCount) { 271 Succ->removePredecessor(this, /*Multiple=*/false); 272 auto I = succ_begin(); 273 auto BI = BranchInfo.begin(); 274 for (; I != succ_end(); ++I) { 275 assert(BI != BranchInfo.end() && "missing BranchInfo entry"); 276 if (*I == Succ) 277 break; 278 ++BI; 279 } 280 assert(I != succ_end() && "no such successor!"); 281 282 *I = NewSucc; 283 *BI = BinaryBranchInfo{Count, MispredictedCount}; 284 NewSucc->addPredecessor(this); 285 } 286 287 void BinaryBasicBlock::removeAllSuccessors() { 288 SmallPtrSet<BinaryBasicBlock *, 2> UniqSuccessors(succ_begin(), succ_end()); 289 for (BinaryBasicBlock *SuccessorBB : UniqSuccessors) 290 SuccessorBB->removePredecessor(this); 291 Successors.clear(); 292 BranchInfo.clear(); 293 } 294 295 void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) { 296 Succ->removePredecessor(this, /*Multiple=*/false); 297 auto I = succ_begin(); 298 auto BI = BranchInfo.begin(); 299 for (; I != succ_end(); ++I) { 300 assert(BI != BranchInfo.end() && "missing BranchInfo entry"); 301 if (*I == Succ) 302 break; 303 ++BI; 304 } 305 assert(I != succ_end() && "no such successor!"); 306 307 Successors.erase(I); 308 BranchInfo.erase(BI); 309 } 310 311 void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) { 312 Predecessors.push_back(Pred); 313 } 314 315 void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred, 316 bool Multiple) { 317 // Note: the predecessor could be listed multiple times. 318 bool Erased = false; 319 for (auto PredI = Predecessors.begin(); PredI != Predecessors.end();) { 320 if (*PredI == Pred) { 321 Erased = true; 322 PredI = Predecessors.erase(PredI); 323 if (!Multiple) 324 return; 325 } else { 326 ++PredI; 327 } 328 } 329 assert(Erased && "Pred is not a predecessor of this block!"); 330 (void)Erased; 331 } 332 333 void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) { 334 assert(succ_size() == 2 && Successors[0] == Successors[1] && 335 "conditional successors expected"); 336 337 BinaryBasicBlock *Succ = Successors[0]; 338 const BinaryBranchInfo CondBI = BranchInfo[0]; 339 const BinaryBranchInfo UncondBI = BranchInfo[1]; 340 341 eraseInstruction(findInstruction(CondBranch)); 342 343 Successors.clear(); 344 BranchInfo.clear(); 345 346 Successors.push_back(Succ); 347 348 uint64_t Count = COUNT_NO_PROFILE; 349 if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE) 350 Count = CondBI.Count + UncondBI.Count; 351 BranchInfo.push_back({Count, 0}); 352 } 353 354 void BinaryBasicBlock::updateJumpTableSuccessors() { 355 const JumpTable *JT = getJumpTable(); 356 assert(JT && "Expected jump table instruction."); 357 358 // Clear existing successors. 359 removeAllSuccessors(); 360 361 // Generate the list of successors in deterministic order without duplicates. 362 SmallVector<BinaryBasicBlock *, 16> SuccessorBBs; 363 for (const MCSymbol *Label : JT->Entries) { 364 BinaryBasicBlock *BB = getFunction()->getBasicBlockForLabel(Label); 365 // Ignore __builtin_unreachable() 366 if (!BB) { 367 assert(Label == getFunction()->getFunctionEndLabel() && 368 "JT label should match a block or end of function."); 369 continue; 370 } 371 SuccessorBBs.emplace_back(BB); 372 } 373 llvm::sort(SuccessorBBs, 374 [](const BinaryBasicBlock *BB1, const BinaryBasicBlock *BB2) { 375 return BB1->getInputOffset() < BB2->getInputOffset(); 376 }); 377 SuccessorBBs.erase(std::unique(SuccessorBBs.begin(), SuccessorBBs.end()), 378 SuccessorBBs.end()); 379 380 for (BinaryBasicBlock *BB : SuccessorBBs) 381 addSuccessor(BB); 382 } 383 384 void BinaryBasicBlock::adjustExecutionCount(double Ratio) { 385 auto adjustedCount = [&](uint64_t Count) -> uint64_t { 386 double NewCount = Count * Ratio; 387 if (!NewCount && Count && (Ratio > 0.0)) 388 NewCount = 1; 389 return NewCount; 390 }; 391 392 setExecutionCount(adjustedCount(getKnownExecutionCount())); 393 for (BinaryBranchInfo &BI : branch_info()) { 394 if (BI.Count != COUNT_NO_PROFILE) 395 BI.Count = adjustedCount(BI.Count); 396 if (BI.MispredictedCount != COUNT_INFERRED) 397 BI.MispredictedCount = adjustedCount(BI.MispredictedCount); 398 } 399 } 400 401 bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB, const MCSymbol *&FBB, 402 MCInst *&CondBranch, 403 MCInst *&UncondBranch) { 404 auto &MIB = Function->getBinaryContext().MIB; 405 return MIB->analyzeBranch(Instructions.begin(), Instructions.end(), TBB, FBB, 406 CondBranch, UncondBranch); 407 } 408 409 bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const { 410 auto &MIB = Function->getBinaryContext().MIB; 411 ArrayRef<MCInst> Insts = Instructions; 412 return MIB->isMacroOpFusionPair(Insts.slice(I - begin())); 413 } 414 415 BinaryBasicBlock::const_iterator 416 BinaryBasicBlock::getMacroOpFusionPair() const { 417 if (!Function->getBinaryContext().isX86()) 418 return end(); 419 420 if (getNumNonPseudos() < 2 || succ_size() != 2) 421 return end(); 422 423 auto RI = getLastNonPseudo(); 424 assert(RI != rend() && "cannot have an empty block with 2 successors"); 425 426 BinaryContext &BC = Function->getBinaryContext(); 427 428 // Skip instruction if it's an unconditional branch following 429 // a conditional one. 430 if (BC.MIB->isUnconditionalBranch(*RI)) 431 ++RI; 432 433 if (!BC.MIB->isConditionalBranch(*RI)) 434 return end(); 435 436 // Start checking with instruction preceding the conditional branch. 437 ++RI; 438 if (RI == rend()) 439 return end(); 440 441 auto II = std::prev(RI.base()); // convert to a forward iterator 442 if (isMacroOpFusionPair(II)) 443 return II; 444 445 return end(); 446 } 447 448 MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) { 449 BinaryContext &BC = Function->getBinaryContext(); 450 auto Itr = rbegin(); 451 bool Check = Pos ? false : true; 452 MCInst *FirstTerminator = nullptr; 453 while (Itr != rend()) { 454 if (!Check) { 455 if (&*Itr == Pos) 456 Check = true; 457 ++Itr; 458 continue; 459 } 460 if (BC.MIB->isTerminator(*Itr)) 461 FirstTerminator = &*Itr; 462 ++Itr; 463 } 464 return FirstTerminator; 465 } 466 467 bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) { 468 BinaryContext &BC = Function->getBinaryContext(); 469 auto Itr = rbegin(); 470 while (Itr != rend()) { 471 if (&*Itr == Pos) 472 return false; 473 if (BC.MIB->isTerminator(*Itr)) 474 return true; 475 ++Itr; 476 } 477 return false; 478 } 479 480 bool BinaryBasicBlock::swapConditionalSuccessors() { 481 if (succ_size() != 2) 482 return false; 483 484 std::swap(Successors[0], Successors[1]); 485 std::swap(BranchInfo[0], BranchInfo[1]); 486 return true; 487 } 488 489 void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) { 490 assert(isSuccessor(Successor)); 491 BinaryContext &BC = Function->getBinaryContext(); 492 MCInst NewInst; 493 std::unique_lock<llvm::sys::RWMutex> Lock(BC.CtxMutex); 494 BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get()); 495 Instructions.emplace_back(std::move(NewInst)); 496 } 497 498 void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) { 499 BinaryContext &BC = Function->getBinaryContext(); 500 MCInst NewInst; 501 BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get()); 502 Instructions.emplace_back(std::move(NewInst)); 503 } 504 505 uint32_t BinaryBasicBlock::getNumCalls() const { 506 uint32_t N = 0; 507 BinaryContext &BC = Function->getBinaryContext(); 508 for (const MCInst &Instr : Instructions) { 509 if (BC.MIB->isCall(Instr)) 510 ++N; 511 } 512 return N; 513 } 514 515 uint32_t BinaryBasicBlock::getNumPseudos() const { 516 #ifndef NDEBUG 517 BinaryContext &BC = Function->getBinaryContext(); 518 uint32_t N = 0; 519 for (const MCInst &Instr : Instructions) 520 if (BC.MIB->isPseudo(Instr)) 521 ++N; 522 523 if (N != NumPseudos) { 524 errs() << "BOLT-ERROR: instructions for basic block " << getName() 525 << " in function " << *Function << ": calculated pseudos " << N 526 << ", set pseudos " << NumPseudos << ", size " << size() << '\n'; 527 llvm_unreachable("pseudos mismatch"); 528 } 529 #endif 530 return NumPseudos; 531 } 532 533 ErrorOr<std::pair<double, double>> 534 BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const { 535 if (Function->hasValidProfile()) { 536 uint64_t TotalCount = 0; 537 uint64_t TotalMispreds = 0; 538 for (const BinaryBranchInfo &BI : BranchInfo) { 539 if (BI.Count != COUNT_NO_PROFILE) { 540 TotalCount += BI.Count; 541 TotalMispreds += BI.MispredictedCount; 542 } 543 } 544 545 if (TotalCount > 0) { 546 auto Itr = llvm::find(Successors, Succ); 547 assert(Itr != Successors.end()); 548 const BinaryBranchInfo &BI = BranchInfo[Itr - Successors.begin()]; 549 if (BI.Count && BI.Count != COUNT_NO_PROFILE) { 550 if (TotalMispreds == 0) 551 TotalMispreds = 1; 552 return std::make_pair(double(BI.Count) / TotalCount, 553 double(BI.MispredictedCount) / TotalMispreds); 554 } 555 } 556 } 557 return make_error_code(llvm::errc::result_out_of_range); 558 } 559 560 void BinaryBasicBlock::dump() const { 561 BinaryContext &BC = Function->getBinaryContext(); 562 if (Label) 563 outs() << Label->getName() << ":\n"; 564 BC.printInstructions(outs(), Instructions.begin(), Instructions.end(), 565 getOffset(), Function); 566 outs() << "preds:"; 567 for (auto itr = pred_begin(); itr != pred_end(); ++itr) { 568 outs() << " " << (*itr)->getName(); 569 } 570 outs() << "\nsuccs:"; 571 for (auto itr = succ_begin(); itr != succ_end(); ++itr) { 572 outs() << " " << (*itr)->getName(); 573 } 574 outs() << "\n"; 575 } 576 577 uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const { 578 return Function->getBinaryContext().computeCodeSize(begin(), end(), Emitter); 579 } 580 581 BinaryBasicBlock::BinaryBranchInfo & 582 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) { 583 return const_cast<BinaryBranchInfo &>( 584 static_cast<const BinaryBasicBlock &>(*this).getBranchInfo(Succ)); 585 } 586 587 const BinaryBasicBlock::BinaryBranchInfo & 588 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) const { 589 const auto Zip = llvm::zip(successors(), branch_info()); 590 const auto Result = llvm::find_if( 591 Zip, [&](const auto &Tuple) { return std::get<0>(Tuple) == &Succ; }); 592 assert(Result != Zip.end() && "Cannot find target in successors"); 593 return std::get<1>(*Result); 594 } 595 596 BinaryBasicBlock::BinaryBranchInfo & 597 BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) { 598 auto BI = branch_info_begin(); 599 for (BinaryBasicBlock *BB : successors()) { 600 if (BB->getLabel() == Label) 601 return *BI; 602 ++BI; 603 } 604 605 llvm_unreachable("Invalid successor"); 606 return *BI; 607 } 608 609 BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) { 610 assert(II != end() && "expected iterator pointing to instruction"); 611 612 BinaryBasicBlock *NewBlock = getFunction()->addBasicBlock(); 613 614 // Adjust successors/predecessors and propagate the execution count. 615 moveAllSuccessorsTo(NewBlock); 616 addSuccessor(NewBlock, getExecutionCount(), 0); 617 618 // Set correct CFI state for the new block. 619 NewBlock->setCFIState(getCFIStateAtInstr(&*II)); 620 621 // Move instructions over. 622 adjustNumPseudos(II, end(), -1); 623 NewBlock->addInstructions(II, end()); 624 Instructions.erase(II, end()); 625 626 return NewBlock; 627 } 628 629 void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) { 630 if (!LocSyms) 631 return; 632 633 const uint64_t BBAddress = getOutputAddressRange().first; 634 const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel()); 635 for (const auto &LocSymKV : *LocSyms) { 636 const uint32_t InputFunctionOffset = LocSymKV.first; 637 const uint32_t OutputOffset = static_cast<uint32_t>( 638 Layout.getSymbolOffset(*LocSymKV.second) - BBOffset); 639 getOffsetTranslationTable().emplace_back( 640 std::make_pair(OutputOffset, InputFunctionOffset)); 641 642 // Update reverse (relative to BAT) address lookup table for function. 643 if (getFunction()->requiresAddressTranslation()) { 644 getFunction()->getInputOffsetToAddressMap().emplace( 645 std::make_pair(InputFunctionOffset, OutputOffset + BBAddress)); 646 } 647 } 648 LocSyms.reset(nullptr); 649 } 650 651 } // namespace bolt 652 } // namespace llvm 653