//===- bolt/Utils/Utils.cpp - Common helper functions ---------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Common helper functions. // //===----------------------------------------------------------------------===// #include "bolt/Utils/Utils.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/MC/MCDwarf.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" namespace llvm { namespace bolt { void report_error(StringRef Message, std::error_code EC) { assert(EC); errs() << "BOLT-ERROR: '" << Message << "': " << EC.message() << ".\n"; exit(1); } void report_error(StringRef Message, Error E) { assert(E); errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E)) << ".\n"; exit(1); } void check_error(std::error_code EC, StringRef Message) { if (!EC) return; report_error(Message, EC); } void check_error(Error E, Twine Message) { if (!E) return; handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) { llvm::errs() << "BOLT-ERROR: '" << Message << "': " << EIB.message() << '\n'; exit(1); }); } std::string getEscapedName(const StringRef &Name) { std::string Output = Name.str(); for (size_t I = 0; I < Output.size(); ++I) if (Output[I] == ' ' || Output[I] == '\\') Output.insert(I++, 1, '\\'); return Output; } std::string getUnescapedName(const StringRef &Name) { std::string Output = Name.str(); for (size_t I = 0; I < Output.size(); ++I) if (Output[I] == '\\') Output.erase(I++, 1); return Output; } std::optional getCommonName(const StringRef Name, bool KeepSuffix, ArrayRef Suffixes) { for (StringRef Suffix : Suffixes) { size_t LTOSuffixPos = Name.find(Suffix); if (LTOSuffixPos != StringRef::npos) return Name.substr(0, LTOSuffixPos + (KeepSuffix ? Suffix.size() : 0)); } return std::nullopt; } std::optional getLTOCommonName(const StringRef Name) { return getCommonName(Name, true, {".__uniq.", ".lto_priv.", ".constprop.", ".llvm."}); } std::optional readDWARFExpressionTargetReg(StringRef ExprBytes) { uint8_t Opcode = ExprBytes[0]; if (Opcode == dwarf::DW_CFA_def_cfa_expression) return std::nullopt; assert((Opcode == dwarf::DW_CFA_expression || Opcode == dwarf::DW_CFA_val_expression) && "invalid DWARF expression CFI"); assert(ExprBytes.size() > 1 && "DWARF expression CFI is too short"); const uint8_t *const Start = reinterpret_cast(ExprBytes.drop_front(1).data()); const uint8_t *const End = reinterpret_cast(Start + ExprBytes.size() - 1); uint8_t Reg = decodeULEB128(Start, nullptr, End); return Reg; } } // namespace bolt bool operator==(const llvm::MCCFIInstruction &L, const llvm::MCCFIInstruction &R) { if (L.getOperation() != R.getOperation()) return false; switch (L.getOperation()) { case MCCFIInstruction::OpRestore: case MCCFIInstruction::OpSameValue: case MCCFIInstruction::OpUndefined: case MCCFIInstruction::OpDefCfaRegister: return L.getRegister() == R.getRegister(); case MCCFIInstruction::OpRegister: return L.getRegister() == R.getRegister() && L.getRegister2() == R.getRegister2(); case MCCFIInstruction::OpOffset: case MCCFIInstruction::OpRelOffset: case MCCFIInstruction::OpDefCfa: return L.getRegister() == R.getRegister() && L.getOffset() == R.getOffset(); case MCCFIInstruction::OpEscape: return L.getValues() == R.getValues(); case MCCFIInstruction::OpRememberState: case MCCFIInstruction::OpRestoreState: return true; case MCCFIInstruction::OpDefCfaOffset: case MCCFIInstruction::OpAdjustCfaOffset: return L.getOffset() == R.getOffset(); default: return false; } } } // namespace llvm