xref: /llvm-project/bolt/lib/Utils/Utils.cpp (revision a66ce58ac6f338c91cccb9801bca04efae9f3f37)
12f09f445SMaksim Panchenko //===- bolt/Utils/Utils.cpp - Common helper functions ---------------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
9a34c753fSRafael Auler // Common helper functions.
10a34c753fSRafael Auler //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
14a34c753fSRafael Auler #include "llvm/BinaryFormat/Dwarf.h"
15a34c753fSRafael Auler #include "llvm/MC/MCDwarf.h"
16a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
17a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h"
18a34c753fSRafael Auler 
19a34c753fSRafael Auler namespace llvm {
20a34c753fSRafael Auler namespace bolt {
21a34c753fSRafael Auler 
22a34c753fSRafael Auler void report_error(StringRef Message, std::error_code EC) {
23a34c753fSRafael Auler   assert(EC);
24a34c753fSRafael Auler   errs() << "BOLT-ERROR: '" << Message << "': " << EC.message() << ".\n";
25a34c753fSRafael Auler   exit(1);
26a34c753fSRafael Auler }
27a34c753fSRafael Auler 
28a34c753fSRafael Auler void report_error(StringRef Message, Error E) {
29a34c753fSRafael Auler   assert(E);
30a34c753fSRafael Auler   errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E))
31a34c753fSRafael Auler          << ".\n";
32a34c753fSRafael Auler   exit(1);
33a34c753fSRafael Auler }
34a34c753fSRafael Auler 
35a34c753fSRafael Auler void check_error(std::error_code EC, StringRef Message) {
36a34c753fSRafael Auler   if (!EC)
37a34c753fSRafael Auler     return;
38a34c753fSRafael Auler   report_error(Message, EC);
39a34c753fSRafael Auler }
40a34c753fSRafael Auler 
41a34c753fSRafael Auler void check_error(Error E, Twine Message) {
42a34c753fSRafael Auler   if (!E)
43a34c753fSRafael Auler     return;
44a34c753fSRafael Auler   handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
45a34c753fSRafael Auler     llvm::errs() << "BOLT-ERROR: '" << Message << "': " << EIB.message()
46a34c753fSRafael Auler                  << '\n';
47a34c753fSRafael Auler     exit(1);
48a34c753fSRafael Auler   });
49a34c753fSRafael Auler }
50a34c753fSRafael Auler 
51a34c753fSRafael Auler std::string getEscapedName(const StringRef &Name) {
52a34c753fSRafael Auler   std::string Output = Name.str();
53883bf0e8SAmir Ayupov   for (size_t I = 0; I < Output.size(); ++I)
54a34c753fSRafael Auler     if (Output[I] == ' ' || Output[I] == '\\')
55a34c753fSRafael Auler       Output.insert(I++, 1, '\\');
56a34c753fSRafael Auler 
57a34c753fSRafael Auler   return Output;
58a34c753fSRafael Auler }
59a34c753fSRafael Auler 
60a34c753fSRafael Auler std::string getUnescapedName(const StringRef &Name) {
61a34c753fSRafael Auler   std::string Output = Name.str();
62883bf0e8SAmir Ayupov   for (size_t I = 0; I < Output.size(); ++I)
63a34c753fSRafael Auler     if (Output[I] == '\\')
64a34c753fSRafael Auler       Output.erase(I++, 1);
65a34c753fSRafael Auler 
66a34c753fSRafael Auler   return Output;
67a34c753fSRafael Auler }
68a34c753fSRafael Auler 
69*a66ce58aSAmir Ayupov std::optional<StringRef> getCommonName(const StringRef Name, bool KeepSuffix,
70*a66ce58aSAmir Ayupov                                        ArrayRef<StringRef> Suffixes) {
71*a66ce58aSAmir Ayupov   for (StringRef Suffix : Suffixes) {
72dbb7316eSAmir Ayupov     size_t LTOSuffixPos = Name.find(Suffix);
73dbb7316eSAmir Ayupov     if (LTOSuffixPos != StringRef::npos)
74*a66ce58aSAmir Ayupov       return Name.substr(0, LTOSuffixPos + (KeepSuffix ? Suffix.size() : 0));
75dbb7316eSAmir Ayupov   }
76dbb7316eSAmir Ayupov   return std::nullopt;
77dbb7316eSAmir Ayupov }
78dbb7316eSAmir Ayupov 
79*a66ce58aSAmir Ayupov std::optional<StringRef> getLTOCommonName(const StringRef Name) {
80*a66ce58aSAmir Ayupov   return getCommonName(Name, true,
81*a66ce58aSAmir Ayupov                        {".__uniq.", ".lto_priv.", ".constprop.", ".llvm."});
82*a66ce58aSAmir Ayupov }
83*a66ce58aSAmir Ayupov 
8476cfea0cSAmir Ayupov std::optional<uint8_t> readDWARFExpressionTargetReg(StringRef ExprBytes) {
85a34c753fSRafael Auler   uint8_t Opcode = ExprBytes[0];
86a34c753fSRafael Auler   if (Opcode == dwarf::DW_CFA_def_cfa_expression)
87e324a80fSKazu Hirata     return std::nullopt;
88a34c753fSRafael Auler   assert((Opcode == dwarf::DW_CFA_expression ||
89a34c753fSRafael Auler           Opcode == dwarf::DW_CFA_val_expression) &&
90a34c753fSRafael Auler          "invalid DWARF expression CFI");
91a34c753fSRafael Auler   assert(ExprBytes.size() > 1 && "DWARF expression CFI is too short");
92a34c753fSRafael Auler   const uint8_t *const Start =
93a34c753fSRafael Auler       reinterpret_cast<const uint8_t *>(ExprBytes.drop_front(1).data());
94a34c753fSRafael Auler   const uint8_t *const End =
95a34c753fSRafael Auler       reinterpret_cast<const uint8_t *>(Start + ExprBytes.size() - 1);
96a34c753fSRafael Auler   uint8_t Reg = decodeULEB128(Start, nullptr, End);
97a34c753fSRafael Auler   return Reg;
98a34c753fSRafael Auler }
99a34c753fSRafael Auler 
100a34c753fSRafael Auler } // namespace bolt
101a34c753fSRafael Auler 
102a34c753fSRafael Auler bool operator==(const llvm::MCCFIInstruction &L,
103a34c753fSRafael Auler                 const llvm::MCCFIInstruction &R) {
104a34c753fSRafael Auler   if (L.getOperation() != R.getOperation())
105a34c753fSRafael Auler     return false;
106a34c753fSRafael Auler   switch (L.getOperation()) {
107a34c753fSRafael Auler   case MCCFIInstruction::OpRestore:
108a34c753fSRafael Auler   case MCCFIInstruction::OpSameValue:
109a34c753fSRafael Auler   case MCCFIInstruction::OpUndefined:
110a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaRegister:
111a34c753fSRafael Auler     return L.getRegister() == R.getRegister();
112a34c753fSRafael Auler   case MCCFIInstruction::OpRegister:
113a34c753fSRafael Auler     return L.getRegister() == R.getRegister() &&
114a34c753fSRafael Auler            L.getRegister2() == R.getRegister2();
115a34c753fSRafael Auler   case MCCFIInstruction::OpOffset:
116a34c753fSRafael Auler   case MCCFIInstruction::OpRelOffset:
117a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfa:
118a34c753fSRafael Auler     return L.getRegister() == R.getRegister() && L.getOffset() == R.getOffset();
119a34c753fSRafael Auler   case MCCFIInstruction::OpEscape:
120a34c753fSRafael Auler     return L.getValues() == R.getValues();
121a34c753fSRafael Auler   case MCCFIInstruction::OpRememberState:
122a34c753fSRafael Auler   case MCCFIInstruction::OpRestoreState:
123a34c753fSRafael Auler     return true;
124a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaOffset:
125a34c753fSRafael Auler   case MCCFIInstruction::OpAdjustCfaOffset:
126a34c753fSRafael Auler     return L.getOffset() == R.getOffset();
127a34c753fSRafael Auler   default:
128a34c753fSRafael Auler     return false;
129a34c753fSRafael Auler   }
130a34c753fSRafael Auler }
131a34c753fSRafael Auler 
132a34c753fSRafael Auler } // namespace llvm
133