Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp
213799 views
//=------- CompactUnwindSupport.cpp - Compact Unwind format support -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Compact Unwind support.9//10//===----------------------------------------------------------------------===//1112#include "CompactUnwindSupport.h"1314#include "llvm/ADT/Sequence.h"1516#define DEBUG_TYPE "jitlink"1718namespace llvm {19namespace jitlink {2021Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection,22size_t RecordSize) {2324std::vector<Block *> OriginalBlocks(CompactUnwindSection.blocks().begin(),25CompactUnwindSection.blocks().end());26LLVM_DEBUG({27dbgs() << "In " << G.getName() << " splitting compact unwind section "28<< CompactUnwindSection.getName() << " containing "29<< OriginalBlocks.size() << " initial blocks...\n";30});3132while (!OriginalBlocks.empty()) {33auto *B = OriginalBlocks.back();34OriginalBlocks.pop_back();3536if (B->getSize() == 0) {37LLVM_DEBUG({38dbgs() << " Skipping empty block at "39<< formatv("{0:x16}", B->getAddress()) << "\n";40});41continue;42}4344unsigned NumBlocks = B->getSize() / RecordSize;4546LLVM_DEBUG({47dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())48<< " into " << NumBlocks << " compact unwind record(s)\n";49});5051if (B->getSize() % RecordSize)52return make_error<JITLinkError>(53"Error splitting compact unwind record in " + G.getName() +54": block at " + formatv("{0:x}", B->getAddress()) + " has size " +55formatv("{0:x}", B->getSize()) +56" (not a multiple of CU record size of " +57formatv("{0:x}", RecordSize) + ")");5859auto Blocks =60G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {61return Idx * RecordSize;62}));6364for (auto *CURec : Blocks) {65bool AddedKeepAlive = false;6667for (auto &E : CURec->edges()) {68if (E.getOffset() == 0) {69LLVM_DEBUG({70dbgs() << " Updating compact unwind record at "71<< CURec->getAddress() << " to point to "72<< (E.getTarget().hasName() ? *E.getTarget().getName()73: StringRef())74<< " (at " << E.getTarget().getAddress() << ")\n";75});7677if (E.getTarget().isExternal())78return make_error<JITLinkError>(79"Error adding keep-alive edge for compact unwind record at " +80formatv("{0:x}", CURec->getAddress()) + ": target " +81*E.getTarget().getName() + " is an external symbol");82auto &TgtBlock = E.getTarget().getBlock();83auto &CURecSym =84G.addAnonymousSymbol(*CURec, 0, RecordSize, false, false);85TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);86AddedKeepAlive = true;87}88}8990if (!AddedKeepAlive)91return make_error<JITLinkError>(92"Error adding keep-alive edge for compact unwind record at " +93formatv("{0:x}", CURec->getAddress()) +94": no outgoing target edge at offset 0");95}96}9798return Error::success();99}100101} // end namespace jitlink102} // end namespace llvm103104105