diff --git a/bolt/include/bolt/Core/BinaryBasicBlock.h b/bolt/include/bolt/Core/BinaryBasicBlock.h index 25cccc4edecf6..fe48d3b4f740d 100644 --- a/bolt/include/bolt/Core/BinaryBasicBlock.h +++ b/bolt/include/bolt/Core/BinaryBasicBlock.h @@ -37,6 +37,11 @@ class JumpTable; class BinaryBasicBlock { public: + enum class RAStateEnum : char { + Unknown, /// Not discovered yet + Signed, + Unsigned, + }; /// Profile execution information for a given edge in CFG. /// /// If MispredictedCount equals COUNT_INFERRED, then we have a profile @@ -350,6 +355,17 @@ class BinaryBasicBlock { BranchInfo.end()); } + RAStateEnum RAState{RAStateEnum::Unknown}; + void setRASigned() { RAState = RAStateEnum::Signed; } + bool isRAStateUnknown() { return RAState == RAStateEnum::Unknown; } + bool isRAStateSigned() { return RAState == RAStateEnum::Signed; } + /// Unsigned should only overwrite Unknown state, and not Signed + void setRAUnsigned() { + if (RAState == RAStateEnum::Unknown) { + RAState = RAStateEnum::Unsigned; + } + } + /// Get instruction at given index. MCInst &getInstructionAtIndex(unsigned Index) { return Instructions[Index]; } diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 3634fed9757ce..937c5c668c9b2 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -16,6 +16,7 @@ #include "bolt/Core/MCPlus.h" #include "bolt/Core/Relocation.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringMap.h" @@ -27,6 +28,7 @@ #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -546,6 +548,27 @@ class MCPlusBuilder { return Analysis->isCall(Inst) || isTailCall(Inst); } + virtual std::optional getCalleeName(const MCInst &Inst) const { + assert(isCall(Inst)); + if (MCPlus::getNumPrimeOperands(Inst) != 1 || !Inst.getOperand(0).isExpr()) + return {}; + + const MCSymbol *CalleeSymbol = getTargetSymbol(Inst); + assert(CalleeSymbol != nullptr); + return CalleeSymbol->getName(); + } + + virtual bool isNoReturnCall(const MCInst &Inst) const { + if (!isCall(Inst)) + return false; + auto calleeName = getCalleeName(Inst); + if (calleeName) + for (std::string &Name : opts::AssumeNoReturnFunctions) + if (calleeName->equals(Name)) + return true; + return false; + } + virtual bool isReturn(const MCInst &Inst) const { return Analysis->isReturn(Inst); } @@ -648,6 +671,13 @@ class MCPlusBuilder { llvm_unreachable("not implemented"); return false; } + virtual bool isPAuth(MCInst &Inst) const { + llvm_unreachable("not implemented"); + } + + virtual bool isPSign(MCInst &Inst) const { + llvm_unreachable("not implemented"); + } virtual bool isCleanRegXOR(const MCInst &Inst) const { llvm_unreachable("not implemented"); diff --git a/bolt/include/bolt/Passes/InsertNegateRAStatePass.h b/bolt/include/bolt/Passes/InsertNegateRAStatePass.h new file mode 100644 index 0000000000000..ac1a2f4cf7327 --- /dev/null +++ b/bolt/include/bolt/Passes/InsertNegateRAStatePass.h @@ -0,0 +1,33 @@ +#ifndef BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS +#define BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS + +#include "bolt/Passes/BinaryPasses.h" +#include + +namespace llvm { +namespace bolt { + +class InsertNegateRAState : public BinaryFunctionPass { +public: + explicit InsertNegateRAState() : BinaryFunctionPass(false) {} + + const char *getName() const override { return "insert-negate-ra-state-pass"; } + + /// Pass entry point + Error runOnFunctions(BinaryContext &BC) override; + void runOnFunction(BinaryFunction &BF); + bool addNegateRAStateAfterPacOrAuth(BinaryFunction &BF); + bool BBhasAUTH(BinaryContext &BC, BinaryBasicBlock *BB); + bool BBhasSIGN(BinaryContext &BC, BinaryBasicBlock *BB); + void explore_call_graph(BinaryContext &BC, BinaryBasicBlock *BB); + void process_signed_BB(BinaryContext &BC, BinaryBasicBlock *BB, + std::stack *SignedStack, + std::stack *UnsignedStack); + void process_unsigned_BB(BinaryContext &BC, BinaryBasicBlock *BB, + std::stack *SignedStack, + std::stack *UnsignedStack); +}; + +} // namespace bolt +} // namespace llvm +#endif diff --git a/bolt/include/bolt/Utils/CommandLineOpts.h b/bolt/include/bolt/Utils/CommandLineOpts.h index 04bf7db5de952..dcdcb0ed84cfc 100644 --- a/bolt/include/bolt/Utils/CommandLineOpts.h +++ b/bolt/include/bolt/Utils/CommandLineOpts.h @@ -62,6 +62,13 @@ extern llvm::cl::opt TimeOpts; extern llvm::cl::opt UseOldText; extern llvm::cl::opt UpdateDebugSections; +extern llvm::cl::list AssumeNoReturnFunctions; +extern llvm::cl::opt AssumeNoReturnFunctionsFile; + +/// Reads names from FunctionNamesFile and adds them to FunctionNames. +void populateFunctionNames(const llvm::cl::opt &FunctionNamesFile, + llvm::cl::list &FunctionNames); + // The default verbosity level (0) is pretty terse, level 1 is fairly // verbose and usually prints some informational message for every // function processed. Level 2 is for the noisiest of messages and diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp index 2a2192b79bb4b..bc1d3f112f2ed 100644 --- a/bolt/lib/Core/BinaryBasicBlock.cpp +++ b/bolt/lib/Core/BinaryBasicBlock.cpp @@ -201,7 +201,11 @@ int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const { InstrSeen = (&Inst == Instr); continue; } - if (Function->getBinaryContext().MIB->isCFI(Inst)) { + // Fix: ignoring OpNegateRAState CFIs here, as they dont have a "State" + // number associated with them. + if (Function->getBinaryContext().MIB->isCFI(Inst) && + (Function->getCFIFor(Inst)->getOperation() != + MCCFIInstruction::OpNegateRAState)) { LastCFI = &Inst; break; } diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 5da777411ba7a..34dd5136f9918 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -2155,7 +2155,8 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { addCFIPlaceholders(Offset, InsertBB); } - const bool IsBlockEnd = MIB->isTerminator(Instr); + const bool IsBlockEnd = + MIB->isTerminator(Instr) || MIB->isNoReturnCall(Instr); IsLastInstrNop = MIB->isNoop(Instr); if (!IsLastInstrNop) LastInstrOffset = Offset; @@ -2242,8 +2243,11 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { // // Conditional tail call is a special case since we don't add a taken // branch successor for it. - IsPrevFT = !MIB->isTerminator(*LastInstr) || - MIB->getConditionalTailCall(*LastInstr); + if (MIB->isNoReturnCall(*LastInstr)) + IsPrevFT = false; + else + IsPrevFT = !MIB->isTerminator(*LastInstr) || + MIB->getConditionalTailCall(*LastInstr); } else if (BB->succ_size() == 1) { IsPrevFT = MIB->isConditionalBranch(*LastInstr); } else { @@ -2596,6 +2600,7 @@ struct CFISnapshot { void advanceTo(int32_t State) { for (int32_t I = CurState, E = State; I != E; ++I) { const MCCFIInstruction &Instr = FDE[I]; + assert(Instr.getOperation() != MCCFIInstruction::OpNegateRAState); if (Instr.getOperation() != MCCFIInstruction::OpRestoreState) { update(Instr, I); continue; diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index 0b2e63b8ca6a7..f528db8449dbd 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -632,8 +632,10 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { // DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same // id but mean different things. The latter is used in AArch64. if (Function.getBinaryContext().isAArch64()) { - Function.addCFIInstruction( - Offset, MCCFIInstruction::createNegateRAState(nullptr)); + // Fix: not adding OpNegateRAState since the location they are needed + // depends on the order of BasicBlocks, which changes during + // optimizations. They are generated in InsertNegateRAStatePass after + // optimizations instead. break; } if (opts::Verbosity >= 1) diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 03d3dd75a0336..0cce08f650ae7 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -1852,17 +1852,16 @@ Error InlineMemcpy::runOnFunctions(BinaryContext &BC) { for (auto II = BB.begin(); II != BB.end(); ++II) { MCInst &Inst = *II; - if (!BC.MIB->isCall(Inst) || MCPlus::getNumPrimeOperands(Inst) != 1 || - !Inst.getOperand(0).isExpr()) + if (!BC.MIB->isCall(Inst)) continue; - - const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Inst); - if (CalleeSymbol->getName() != "memcpy" && - CalleeSymbol->getName() != "memcpy@PLT" && - CalleeSymbol->getName() != "_memcpy8") + std::optional CalleeName = BC.MIB->getCalleeName(Inst); + if (!CalleeName) + continue; + if (*CalleeName != "memcpy" && *CalleeName != "memcpy@PLT" && + *CalleeName != "_memcpy8") continue; - const bool IsMemcpy8 = (CalleeSymbol->getName() == "_memcpy8"); + const bool IsMemcpy8 = (*CalleeName == "_memcpy8"); const bool IsTailCall = BC.MIB->isTailCall(Inst); const InstructionListType NewCode = @@ -1951,13 +1950,12 @@ Error SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) { for (auto II = CurBB->begin(); II != CurBB->end(); ++II) { MCInst &Inst = *II; - if (!BC.MIB->isCall(Inst) || MCPlus::getNumPrimeOperands(Inst) != 1 || - !Inst.getOperand(0).isExpr()) + if (!BC.MIB->isCall(Inst)) continue; - - const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Inst); - if (CalleeSymbol->getName() != "memcpy" && - CalleeSymbol->getName() != "memcpy@PLT") + std::optional CalleeName = BC.MIB->getCalleeName(Inst); + if (!CalleeName) + continue; + if (*CalleeName != "memcpy" && *CalleeName != "memcpy@PLT") continue; if (BC.MIB->isTailCall(Inst)) diff --git a/bolt/lib/Passes/CMakeLists.txt b/bolt/lib/Passes/CMakeLists.txt index 1c1273b3d2420..d7864e3030511 100644 --- a/bolt/lib/Passes/CMakeLists.txt +++ b/bolt/lib/Passes/CMakeLists.txt @@ -17,6 +17,7 @@ add_llvm_library(LLVMBOLTPasses IdenticalCodeFolding.cpp IndirectCallPromotion.cpp Inliner.cpp + InsertNegateRAStatePass.cpp Instrumentation.cpp JTFootprintReduction.cpp LongJmp.cpp diff --git a/bolt/lib/Passes/InsertNegateRAStatePass.cpp b/bolt/lib/Passes/InsertNegateRAStatePass.cpp new file mode 100644 index 0000000000000..e7c3bdb050813 --- /dev/null +++ b/bolt/lib/Passes/InsertNegateRAStatePass.cpp @@ -0,0 +1,241 @@ +#include "bolt/Passes/InsertNegateRAStatePass.h" +#include "bolt/Core/BinaryFunction.h" +#include "bolt/Core/ParallelUtilities.h" +#include "bolt/Utils/CommandLineOpts.h" +#include +#include +#include + +using namespace llvm; + +namespace llvm { +namespace bolt { + +void InsertNegateRAState::runOnFunction(BinaryFunction &BF) { + BinaryContext &BC = BF.getBinaryContext(); + + if (BF.getState() == BinaryFunction::State::Empty) { + return; + } + + if (BF.getState() != BinaryFunction::State::CFG && + BF.getState() != BinaryFunction::State::CFG_Finalized) { + BC.outs() << "BOLT-INFO: No CFG for " << BF.getPrintName() + << " in InsertNegateRAStatePass\n"; + return; + } + + if (BF.isIgnored()) + return; + + if (!addNegateRAStateAfterPacOrAuth(BF)) { + // none inserted, function doesn't need more work + return; + } + + auto FirstBB = BF.begin(); + explore_call_graph(BC, &(*FirstBB)); + + // We have to do the walk again, starting from any undiscovered autiasp + // instructions, because some autiasp might not be reachable because of + // indirect branches but we know that autiasp block should have a Signed + // state, so we can work out other Unkown states starting from these nodes. + for (BinaryBasicBlock &BB : BF) { + if (BBhasAUTH(BC, &BB) && BB.isRAStateUnknown()) { + BB.setRASigned(); + explore_call_graph(BC, &BB); + } + } + + // insert negateRAState-s where there is a State boundary: + // that is: two consecutive BBs have different RA State + BinaryFunction::iterator PrevBB; + bool FirstIter = true; + for (auto BB = BF.begin(); BB != BF.end(); ++BB) { + if (!FirstIter) { + if ((PrevBB->RAState == BinaryBasicBlock::RAStateEnum::Signed && + (*BB).RAState == BinaryBasicBlock::RAStateEnum::Unsigned && + !BBhasAUTH(BC, &(*PrevBB))) || + (PrevBB->RAState == BinaryBasicBlock::RAStateEnum::Signed && + (*BB).RAState == BinaryBasicBlock::RAStateEnum::Signed && + BBhasAUTH(BC, &(*PrevBB)))) { + auto InstRevIter = PrevBB->getLastNonPseudo(); + MCInst LastNonPseudo = *InstRevIter; + auto InstIter = InstRevIter.base(); + BF.addCFIInstruction(&(*PrevBB), InstIter, + MCCFIInstruction::createNegateRAState(nullptr)); + } + } else { + FirstIter = false; + } + PrevBB = BB; + } +} + +void InsertNegateRAState::explore_call_graph(BinaryContext &BC, + BinaryBasicBlock *BB) { + std::stack SignedStack; + std::stack UnsignedStack; + + // start according to the first BB + if (BBhasSIGN(BC, BB)) { + SignedStack.push(BB); + process_signed_BB(BC, BB, &SignedStack, &UnsignedStack); + } else { + UnsignedStack.push(BB); + process_unsigned_BB(BC, BB, &SignedStack, &UnsignedStack); + } + + while (!(SignedStack.empty() && UnsignedStack.empty())) { + if (!SignedStack.empty()) { + BB = SignedStack.top(); + SignedStack.pop(); + process_signed_BB(BC, BB, &SignedStack, &UnsignedStack); + } else if (!UnsignedStack.empty()) { + BB = UnsignedStack.top(); + UnsignedStack.pop(); + process_unsigned_BB(BC, BB, &SignedStack, &UnsignedStack); + } + } +} +void InsertNegateRAState::process_signed_BB( + BinaryContext &BC, BinaryBasicBlock *BB, + std::stack *SignedStack, + std::stack *UnsignedStack) { + + BB->setRASigned(); + + if (BBhasAUTH(BC, BB)) { + // successors of block with autiasp are stored in the Unsigned Stack + for (BinaryBasicBlock *Succ : BB->successors()) { + if (Succ->getFunction() == BB->getFunction() && + Succ->isRAStateUnknown()) { + UnsignedStack->push(Succ); + } + } + } else { + for (BinaryBasicBlock *Succ : BB->successors()) { + if (Succ->getFunction() == BB->getFunction() && + !Succ->isRAStateSigned()) { + SignedStack->push(Succ); + } + } + } + // process predecessors + if (BBhasSIGN(BC, BB)) { + for (BinaryBasicBlock *Pred : BB->predecessors()) { + if (Pred->getFunction() == BB->getFunction() && + Pred->isRAStateUnknown()) { + UnsignedStack->push(Pred); + } + } + } else { + for (BinaryBasicBlock *Pred : BB->predecessors()) { + if (Pred->getFunction() == BB->getFunction() && + !Pred->isRAStateSigned()) { + SignedStack->push(Pred); + } + } + } +} + +void InsertNegateRAState::process_unsigned_BB( + BinaryContext &BC, BinaryBasicBlock *BB, + std::stack *SignedStack, + std::stack *UnsignedStack) { + + BB->setRAUnsigned(); + + if (BBhasSIGN(BC, BB)) { + BB->setRASigned(); + // successors of block with paciasp are stored in the Signed Stack + for (BinaryBasicBlock *Succ : BB->successors()) { + if (Succ->getFunction() == BB->getFunction() && + !Succ->isRAStateSigned()) { + SignedStack->push(Succ); + } + } + } else { + for (BinaryBasicBlock *Succ : BB->successors()) { + if (Succ->getFunction() == BB->getFunction() && + Succ->isRAStateUnknown()) { + UnsignedStack->push(Succ); + } + } + } + + // process predecessors + if (BBhasAUTH(BC, BB)) { + BB->setRASigned(); + for (BinaryBasicBlock *Pred : BB->predecessors()) { + if (Pred->getFunction() == BB->getFunction() && + !Pred->isRAStateSigned()) { + SignedStack->push(Pred); + } + } + } else { + for (BinaryBasicBlock *Pred : BB->predecessors()) { + if (Pred->getFunction() == BB->getFunction() && + Pred->isRAStateUnknown()) { + UnsignedStack->push(Pred); + } + } + } +} + +bool InsertNegateRAState::BBhasAUTH(BinaryContext &BC, BinaryBasicBlock *BB) { + for (auto Iter = BB->begin(); Iter != BB->end(); ++Iter) { + MCInst Inst = *Iter; + if (BC.MIB->isPAuth(Inst)) { + return true; + } + } + return false; +} + +bool InsertNegateRAState::BBhasSIGN(BinaryContext &BC, BinaryBasicBlock *BB) { + for (auto Iter = BB->begin(); Iter != BB->end(); ++Iter) { + MCInst Inst = *Iter; + if (BC.MIB->isPSign(Inst)) { + return true; + } + } + return false; +} + +bool InsertNegateRAState::addNegateRAStateAfterPacOrAuth(BinaryFunction &BF) { + BinaryContext &BC = BF.getBinaryContext(); + bool FoundAny = false; + for (BinaryBasicBlock &BB : BF) { + for (auto Iter = BB.begin(); Iter != BB.end(); ++Iter) { + MCInst Inst = *Iter; + if (BC.MIB->isPSign(Inst)) { + Iter = BF.addCFIInstruction( + &BB, Iter + 1, MCCFIInstruction::createNegateRAState(nullptr)); + FoundAny = true; + } + + if (BC.MIB->isPAuth(Inst)) { + Iter = BF.addCFIInstruction( + &BB, Iter + 1, MCCFIInstruction::createNegateRAState(nullptr)); + FoundAny = true; + } + } + } + return FoundAny; +} + +Error InsertNegateRAState::runOnFunctions(BinaryContext &BC) { + ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { + runOnFunction(BF); + }; + + ParallelUtilities::runOnEachFunction( + BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, nullptr, + "InsertNegateRAStatePass"); + + return Error::success(); +} + +} // end namespace bolt +} // end namespace llvm diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index b090604183348..d11321d8ef93a 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -20,6 +20,7 @@ #include "bolt/Passes/IdenticalCodeFolding.h" #include "bolt/Passes/IndirectCallPromotion.h" #include "bolt/Passes/Inliner.h" +#include "bolt/Passes/InsertNegateRAStatePass.h" #include "bolt/Passes/Instrumentation.h" #include "bolt/Passes/JTFootprintReduction.h" #include "bolt/Passes/LongJmp.h" @@ -499,6 +500,8 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { // targets. No extra instructions after this pass, otherwise we may have // relocations out of range and crash during linking. Manager.registerPass(std::make_unique(PrintLongJmp)); + + Manager.registerPass(std::make_unique()); } // This pass should always run last.* diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 7059a3dd23109..5352a6ec8a8eb 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -269,6 +269,9 @@ MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, const MCInstrInfo *Info, const MCRegisterInfo *RegInfo, const MCSubtargetInfo *STI) { + opts::populateFunctionNames(opts::AssumeNoReturnFunctionsFile, + opts::AssumeNoReturnFunctions); + #ifdef X86_AVAILABLE if (Arch == Triple::x86_64) return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI); @@ -2929,18 +2932,12 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, void RewriteInstance::selectFunctionsToProcess() { // Extend the list of functions to process or skip from a file. - auto populateFunctionNames = [](cl::opt &FunctionNamesFile, - cl::list &FunctionNames) { - if (FunctionNamesFile.empty()) - return; - std::ifstream FuncsFile(FunctionNamesFile, std::ios::in); - std::string FuncName; - while (std::getline(FuncsFile, FuncName)) - FunctionNames.push_back(FuncName); - }; - populateFunctionNames(opts::FunctionNamesFile, opts::ForceFunctionNames); - populateFunctionNames(opts::SkipFunctionNamesFile, opts::SkipFunctionNames); - populateFunctionNames(opts::FunctionNamesFileNR, opts::ForceFunctionNamesNR); + opts::populateFunctionNames(opts::FunctionNamesFile, + opts::ForceFunctionNames); + opts::populateFunctionNames(opts::SkipFunctionNamesFile, + opts::SkipFunctionNames); + opts::populateFunctionNames(opts::FunctionNamesFileNR, + opts::ForceFunctionNamesNR); // Make a set of functions to process to speed up lookups. std::unordered_set ForceFunctionsNR( diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index 7e08e5c81d26f..c07a93c0a1460 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -316,6 +316,12 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { } return false; } + bool isPAuth(MCInst &Inst) const override { + return Inst.getOpcode() == AArch64::AUTIASP; + } + bool isPSign(MCInst &Inst) const override { + return Inst.getOpcode() == AArch64::PACIASP; + } bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From, MCPhysReg &To) const override { diff --git a/bolt/lib/Utils/CommandLineOpts.cpp b/bolt/lib/Utils/CommandLineOpts.cpp index de82420a16713..a72400c560ab0 100644 --- a/bolt/lib/Utils/CommandLineOpts.cpp +++ b/bolt/lib/Utils/CommandLineOpts.cpp @@ -11,7 +11,8 @@ //===----------------------------------------------------------------------===// #include "bolt/Utils/CommandLineOpts.h" -#include "VCSVersion.inc" +#include "llvm/Support/VCSRevision.h" +#include using namespace llvm; @@ -206,11 +207,31 @@ cl::opt UpdateDebugSections( cl::desc("update DWARF debug sections of the executable"), cl::cat(BoltCategory)); +cl::list AssumeNoReturnFunctions( + "noreturnfuncs", cl::CommaSeparated, + cl::desc("List which function names to assume are no-return"), + cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory)); + +cl::opt AssumeNoReturnFunctionsFile( + "noreturnfuncs-file", + cl::desc("file with list of functions to assume are no-return"), cl::Hidden, + cl::cat(BoltCategory)); + cl::opt Verbosity("v", cl::desc("set verbosity level for diagnostic output"), cl::init(0), cl::ZeroOrMore, cl::cat(BoltCategory), cl::sub(cl::SubCommand::getAll())); +void populateFunctionNames(const cl::opt &FunctionNamesFile, + cl::list &FunctionNames) { + if (FunctionNamesFile.empty()) + return; + std::ifstream FuncsFile(FunctionNamesFile, std::ios::in); + std::string FuncName; + while (std::getline(FuncsFile, FuncName)) + FunctionNames.push_back(FuncName); +} + bool processAllFunctions() { if (opts::AggregateOnly) return false; diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h index 5b525c8e56ecc..381a254ce8634 100644 --- a/llvm/include/llvm/ADT/StringRef.h +++ b/llvm/include/llvm/ADT/StringRef.h @@ -177,6 +177,11 @@ namespace llvm { return size() == RHS.size() && compare_insensitive(RHS) == 0; } + /// Check for string equality, ignoring case. + [[nodiscard]] bool equals(StringRef RHS) const { + return Length == RHS.Length && compare(RHS) == 0; + } + /// compare - Compare two strings; the result is negative, zero, or positive /// if this string is lexicographically less than, equal to, or greater than /// the \p RHS.