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