diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -590,6 +590,43 @@ return BF.isSimple() && !BF.isIgnored(); } +namespace { + +// Check for dirty state in MCSymbol objects that might be a consequence +// of running calculateEmittedSize() in parallel, during split functions +// pass. If an inconsistent state is found (symbol already registered or +// already defined), clean it. +void resetMCSymbolState(const MCExpr *Expr) { + if (const MCUnaryExpr *UE = dyn_cast(Expr)) { + resetMCSymbolState(UE->getSubExpr()); + return; + } + if (const MCBinaryExpr *BE = dyn_cast(Expr)) { + resetMCSymbolState(BE->getLHS()); + resetMCSymbolState(BE->getRHS()); + return; + } + if (const MCSymbolRefExpr *SRef = dyn_cast(Expr)) { + const MCSymbol &S = SRef->getSymbol(); + if (S.isDefined()) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S.getName() + << "\" is already defined\n"); + const_cast(&S)->setUndefined(); + } + if (S.isRegistered()) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S.getName() + << "\" is already registered\n"); + const_cast(&S)->setIsRegistered(false); + } + LLVM_DEBUG(if (S.isVariable()) { + dbgs() << "BOLT-DEBUG: Symbol \"" << S.getName() << "\" is variable\n"; + }); + return; + } +} + +} // end anonymous namespace + void LowerAnnotations::runOnFunctions(BinaryContext &BC) { std::vector> PreservedOffsetAnnotations; @@ -623,6 +660,14 @@ // Now record preserved annotations separately and then strip // annotations. for (auto II = BB->begin(); II != BB->end(); ++II) { + // Check for dirty state of MCSymbols caused by running + // calculateEmittedSize in parallel and restore them + for (unsigned OpI = 0, OpE = II->getNumOperands(); OpI != OpE; ++OpI) { + const MCOperand& Operand = II->getOperand(OpI); + if (!Operand.isExpr()) + continue; + resetMCSymbolState(Operand.getExpr()); + } if (BF.requiresAddressTranslation() && BC.MIB->getOffset(*II)) PreservedOffsetAnnotations.emplace_back(&(*II), *BC.MIB->getOffset(*II));