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/CommandLine.h"
17 #include "llvm/Support/LEB128.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 namespace llvm {
21 namespace bolt {
22 
23 void report_error(StringRef Message, std::error_code EC) {
24   assert(EC);
25   errs() << "BOLT-ERROR: '" << Message << "': " << EC.message() << ".\n";
26   exit(1);
27 }
28 
29 void report_error(StringRef Message, Error E) {
30   assert(E);
31   errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E))
32          << ".\n";
33   exit(1);
34 }
35 
36 void check_error(std::error_code EC, StringRef Message) {
37   if (!EC)
38     return;
39   report_error(Message, EC);
40 }
41 
42 void check_error(Error E, Twine Message) {
43   if (!E)
44     return;
45   handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
46     llvm::errs() << "BOLT-ERROR: '" << Message << "': " << EIB.message()
47                  << '\n';
48     exit(1);
49   });
50 }
51 
52 std::string getEscapedName(const StringRef &Name) {
53   std::string Output = Name.str();
54   for (size_t I = 0; I < Output.size(); ++I)
55     if (Output[I] == ' ' || Output[I] == '\\')
56       Output.insert(I++, 1, '\\');
57 
58   return Output;
59 }
60 
61 std::string getUnescapedName(const StringRef &Name) {
62   std::string Output = Name.str();
63   for (size_t I = 0; I < Output.size(); ++I)
64     if (Output[I] == '\\')
65       Output.erase(I++, 1);
66 
67   return Output;
68 }
69 
70 Optional<uint8_t> readDWARFExpressionTargetReg(StringRef ExprBytes) {
71   uint8_t Opcode = ExprBytes[0];
72   if (Opcode == dwarf::DW_CFA_def_cfa_expression)
73     return NoneType();
74   assert((Opcode == dwarf::DW_CFA_expression ||
75           Opcode == dwarf::DW_CFA_val_expression) &&
76          "invalid DWARF expression CFI");
77   assert(ExprBytes.size() > 1 && "DWARF expression CFI is too short");
78   const uint8_t *const Start =
79       reinterpret_cast<const uint8_t *>(ExprBytes.drop_front(1).data());
80   const uint8_t *const End =
81       reinterpret_cast<const uint8_t *>(Start + ExprBytes.size() - 1);
82   uint8_t Reg = decodeULEB128(Start, nullptr, End);
83   return Reg;
84 }
85 
86 } // namespace bolt
87 
88 bool operator==(const llvm::MCCFIInstruction &L,
89                 const llvm::MCCFIInstruction &R) {
90   if (L.getOperation() != R.getOperation())
91     return false;
92   switch (L.getOperation()) {
93   case MCCFIInstruction::OpRestore:
94   case MCCFIInstruction::OpSameValue:
95   case MCCFIInstruction::OpUndefined:
96   case MCCFIInstruction::OpDefCfaRegister:
97     return L.getRegister() == R.getRegister();
98   case MCCFIInstruction::OpRegister:
99     return L.getRegister() == R.getRegister() &&
100            L.getRegister2() == R.getRegister2();
101   case MCCFIInstruction::OpOffset:
102   case MCCFIInstruction::OpRelOffset:
103   case MCCFIInstruction::OpDefCfa:
104     return L.getRegister() == R.getRegister() && L.getOffset() == R.getOffset();
105   case MCCFIInstruction::OpEscape:
106     return L.getValues() == R.getValues();
107   case MCCFIInstruction::OpRememberState:
108   case MCCFIInstruction::OpRestoreState:
109     return true;
110   case MCCFIInstruction::OpDefCfaOffset:
111   case MCCFIInstruction::OpAdjustCfaOffset:
112     return L.getOffset() == R.getOffset();
113   default:
114     return false;
115   }
116 }
117 
118 } // namespace llvm
119